What I will show is how to call ChooseColor, load and save the 16 "custom" colors from file, load and save the selected color to file, and get the Hue, Sat, Lum, Red, Blue and Green from selected color.
Code first then a breakdown:
include masm32rt.inc
IDD_MAIN equ 1000
IDC_COLOR equ 1001
BTN_SELECT equ 1002
IDC_HUE equ 1004
IDC_SAT equ 1005
IDC_LUM equ 1007
IDC_RED equ 1009
IDC_GREEN equ 1011
IDC_BLUE equ 1013
; ChooseColor Dialog equates
; From ColorDlg.h
COLOR_HUE equ 703
COLOR_SAT equ 704
COLOR_LUM equ 705
COLOR_RED equ 706
COLOR_GREEN equ 707
COLOR_BLUE equ 708
DialogProc PROTO hWin:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM
.data
szFile BYTE "settings.ini", 0
szCustomColors BYTE "Custom Colors", 0
szColors BYTE "Colors", 0
szStartColor BYTE "Start", 0
cc CHOOSECOLOR <sizeof cc, ?, ?, 0, ?, CC_FULLOPEN or CC_RGBINIT or CC_ENABLEHOOK, NULL, offset CCHookProc, NULL>
DefColors DWORD 0ff0000h,0ff00h,0ffh,0ffff00h,0ffffh
DWORD 0cc0000h,0cc00h,0cch,0cccc00h,0cccch
DWORD 0800000h,08000h,080h,0808000h,08080h
DWORD 0400000h
ClrSize equ ($ - DefColors)
.data?
hInst DWORD ?
MyColors DWORD ClrSize dup (?)
lpszFile BYTE MAX_PATH + 1 dup (?)
hColorCtl DWORD ?
hBrush DWORD ?
hMain DWORD ?
.code
start:
invoke GetAppPath, offset lpszFile
invoke szCatStr, offset lpszFile, offset szFile
invoke GetModuleHandle, NULL
mov hInst, eax
invoke DialogBoxParam, eax, IDD_MAIN, NULL, offset DialogProc, NULL
invoke ExitProcess, 0
DialogProc proc hWin:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM
mov eax,uMsg
.if eax==WM_INITDIALOG
push hWin
pop hMain
invoke GetDlgItem, hWin, IDC_COLOR
mov hColorCtl, eax
invoke exist, offset lpszFile
.if eax !=0
invoke GetPrivateProfileStruct, offset szCustomColors, offset szColors, offset MyColors, lengthof MyColors, offset lpszFile
invoke GetPrivateProfileStruct, offset szCustomColors, offset szStartColor, offset cc.rgbResult, sizeof CHOOSECOLOR.rgbResult, offset lpszFile
.else
invoke MemCopy, offset DefColors, offset MyColors, ClrSize
mov cc.rgbResult, 00B68427H
.endif
.elseif eax==WM_COMMAND
mov edx,wParam
movzx eax,dx
shr edx,16
.if edx==BN_CLICKED
.if eax==BTN_SELECT
push hInst
pop cc.hInstance
push hWin
pop cc.hwndOwner
mov cc.lpCustColors, offset MyColors
invoke ChooseColor, offset cc
test eax, eax
jz @F
invoke DeleteObject, hBrush
invoke CreateSolidBrush, cc.rgbResult
mov hBrush, eax
invoke InvalidateRect, hColorCtl, NULL, TRUE
@@:
.endif
.endif
.elseif eax == WM_CTLCOLORSTATIC
mov ecx, hColorCtl
.if lParam == ecx
mov eax, hBrush
ret
.endif
.elseif eax==WM_CLOSE
invoke WritePrivateProfileStruct, offset szCustomColors, offset szColors, offset MyColors, lengthof MyColors, offset lpszFile
invoke WritePrivateProfileStruct, offset szCustomColors, offset szStartColor, offset cc.rgbResult, sizeof CHOOSECOLOR.rgbResult, offset lpszFile
invoke DeleteObject, hBrush
invoke EndDialog,hWin,NULL
.else
mov eax,FALSE
ret
.endif
mov eax,TRUE
ret
DialogProc endp
CCHookProc proc hDlg:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM
mov eax,uMsg
.if eax==WM_COMMAND
mov edx,wParam
movzx eax,dx
shr edx,16
.if edx==BN_CLICKED
.if eax==IDOK
invoke GetDlgItemInt, hDlg, COLOR_HUE, NULL, FALSE
invoke SetDlgItemInt, hMain, IDC_HUE, eax, FALSE
invoke GetDlgItemInt, hDlg, COLOR_SAT, NULL, FALSE
invoke SetDlgItemInt, hMain, IDC_SAT, eax, FALSE
invoke GetDlgItemInt, hDlg, COLOR_LUM, NULL, FALSE
invoke SetDlgItemInt, hMain, IDC_LUM, eax, FALSE
invoke GetDlgItemInt, hDlg, COLOR_RED, NULL, FALSE
invoke SetDlgItemInt, hMain, IDC_RED, eax, FALSE
invoke GetDlgItemInt, hDlg, COLOR_GREEN, NULL, FALSE
invoke SetDlgItemInt, hMain, IDC_GREEN, eax, FALSE
invoke GetDlgItemInt, hDlg, COLOR_BLUE, NULL, FALSE
invoke SetDlgItemInt, hMain, IDC_BLUE, eax, FALSE
.endif
.endif
.endif
xor eax, eax
ret
CCHookProc endp
end start
Yeah, I am a bit "lazy" lately and am using dialogs...
; ChooseColor Dialog equates ; From ColorDlg.h COLOR_HUE equ 703 COLOR_SAT equ 704 COLOR_LUM equ 705 COLOR_RED equ 706 COLOR_GREEN equ 707 COLOR_BLUE equ 708
These are the control IDs for the 6 edit controls on the ChooseColor dialog. All of the control IDs can be found in ColorDlg.h (Part of the SDK)
szFile BYTE "settings.ini", 0
szCustomColors BYTE "Custom Colors", 0
szColors BYTE "Colors", 0
szStartColor BYTE "Start", 0
cc CHOOSECOLOR <sizeof cc, ?, ?, ?, ?, CC_FULLOPEN or CC_RGBINIT or CC_ENABLEHOOK, NULL, offset CCHookProc, NULL>
DefColors DWORD 0ff0000h,0ff00h,0ffh,0ffff00h,0ffffh
DWORD 0cc0000h,0cc00h,0cch,0cccc00h,0cccch
DWORD 0800000h,08000h,080h,0808000h,08080h
DWORD 0400000h
ClrSize equ ($ - DefColors)
We will be using ini file APIs to save and load our colors, so our file will be called settings.ini
cc is a "pre-initialized" CHOOSECOLOR structure:
lStructSize We will let the Assembler fill in the structure size,
hwndOwner We don't know the handle of the dialogs owner, so we will leave that as uninitialized (fill it in later)
hInstance Same for the hInstance.
rgbResult, we will leave this uninitialized for now, and fill it in later. If the CC_RGBINIT flag is set (In our case it is) we set the initially set color here.
lpCustColors this is an array of 16 DWORDS that are the custom colors the dialog displays, we will fill this in later.
Flags We are using - CC_FULLOPEN or CC_RGBINIT or CC_ENABLEHOOK
There are a few other flags we can use:
- CC_ANYCOLOR
- CC_ENABLETEMPLATE
- CC_ENABLETEMPLATEHANDLE
- CC_PREVENTFULLOPEN
- CC_SHOWHELP
- CC_SOLIDCOLOR
- CC_FULLOPEN This causes the ChooseColor Dialog to fully open, without this, the user has to press the "Define Custom Color" button.
- CC_RGBINIT This tells the dialog to use the color we give it as the initial color
- CC_ENABLEHOOK This tells the dialog we want to hook into it and pass its messages on to our hook proc
CC_ENABLEHOOK
We will be hooking the BN_CLICKED message and will be looking for a message from the Ok button.
Here is how hooking the ChooseColor dialog works:
You call ChooseColor, and the dialog processes its own WM_INITDIALOG message to set up the dialog, then passes on the WM_INITDIALOG message to our hook proc. If we wanted to get messages from any of the controls, we would subclass the controls here in our WM_INITDIALOG handler.
lCustData this is an application defined value passed to our hook proc, lParam will contain a pointer to the CHOOSECOLOR structure we passed to ChooseColor. We don't need it so it is NULL
lpfnHook the address of our hook proc
lpTemplateName This would be the customized dialog in our resource section. We don't need, so NULL
DefColors is an array of 16 colors we will use to initialize the dialog with if it is the first time our sample app is starting and there is no settings.ini file.
MyColors is an array of DWORD we will pass to the ChooseColor dialog. The dialog will update this array each time a custom color is changed.
DialogProc proc hWin:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM
mov eax,uMsg
.if eax==WM_INITDIALOG
push hWin
pop hMain
invoke GetDlgItem, hWin, IDC_COLOR
mov hColorCtl, eax
invoke exist, offset lpszFile
.if eax !=0
invoke GetPrivateProfileStruct, offset szCustomColors, offset szColors, offset MyColors, lengthof MyColors, offset lpszFile
invoke GetPrivateProfileStruct, offset szCustomColors, offset szStartColor, offset cc.rgbResult, sizeof CHOOSECOLOR.rgbResult, offset lpszFile
.else
invoke MemCopy, offset DefColors, offset MyColors, ClrSize
mov cc.rgbResult, 00B68427H
.endif
.elseif eax==WM_COMMAND
mov edx,wParam
movzx eax,dx
shr edx,16
.if edx==BN_CLICKED
.if eax==BTN_SELECT
push hInst
pop cc.hInstance
push hWin
pop cc.hwndOwner
mov cc.lpCustColors, offset MyColors
invoke ChooseColor, offset cc
test eax, eax
jz @F
invoke DeleteObject, hBrush
invoke CreateSolidBrush, cc.rgbResult
mov hBrush, eax
invoke InvalidateRect, hColorCtl, NULL, TRUE
@@:
.endif
.endif
.elseif eax == WM_CTLCOLORSTATIC
mov ecx, hColorCtl
.if lParam == ecx
mov eax, hBrush
ret
.endif
.elseif eax==WM_CLOSE
invoke WritePrivateProfileStruct, offset szCustomColors, offset szColors, offset MyColors, lengthof MyColors, offset lpszFile
invoke WritePrivateProfileStruct, offset szCustomColors, offset szStartColor, offset cc.rgbResult, sizeof CHOOSECOLOR.rgbResult, offset lpszFile
invoke DeleteObject, hBrush
invoke EndDialog,hWin,NULL
.else
mov eax,FALSE
ret
.endif
mov eax,TRUE
ret
DialogProc endp
In WM_INITDIALOG, we check to see if our settings file exists and if it does we:
Use an underused (IMO) ini API - GetPrivateProfileStruct to load our 16 custom colors and the start color.
If the settings file does NOT exist, we copy our Default colors into MyColors array and set the initial color to a bluey color.
In WM_COMMAND/BN_CLICKED we fill in some missing fields of the cc struct:
We fill in hInstance, hwndOwner and lpCustColors and call ChooseColor and pass it our cc struct.
When the dialog is closed we check to see if the user clicked OK or cancel/X button; if the user selected a color we:
Delete our brush handle, create a new brush with the color from rgbResult, save the brush handle and then force a re paint of our static control on our window to display the selected color. That is done with InvalidateRect.
In WM_CTLCOLORSTATIC we check to see if the message is for our control and if it is we return the handle to our brush.
WM_CLOSE
We save our custom colors array and the selected color to our settings file with WritePrivateProfileStruct, and finally destroy our custom brush.
In our Dialog hook proc, we are only interested in the WM_COMMAND message and if the user clicked OK, this is where we get the text from the Hue, Sat, Lum, Red, Green, and Blue edit controls on the ChooseColor Dialog.
We return zero from our hook proc for ALL messages so the ChooseColor dialog will continue its processing of messages. If we return a non zero, ChooseColor will not process the message. So, if say the user selected red, and you don't want to allow red, return a non zero until the user selected anything but red.
Source and sample program attached.
Attached File(s)
-
ChooseColor.zip (4.04K)
Number of downloads: 122
This post has been edited by GunnerInc: 20 January 2012 - 06:03 PM







MultiQuote


|