I'm working on a little utility that when run, will create a button child window for the user to press to abort the process if desired.
The question is, in createwindow, you need to supply a unique child window identifier. Is there some api that says, give me the next available unused id? I don't really care what the id is, I use the handle, but if it duplicates an id already in use in the calling program, the user cannot access the new child button.
Jim,
I would not be afraid to just use a simple counter as you will never get anywhere near the DWORD limit. You could use the return value from getTickCount if your app does not run over the span of days. With a normal CreateWindowEx() window you can use either the control ID number or the window handle which is always unique so it should not be all that problematic.
Thanks Hutch. It sure would have been nice if createwindow would have returned an error if there was a duplicate!
Quote from: MSDNit must be unique for all child windows with the same parent window.
I've created text labels (static controls) all with the same ID and never had a problem - I just use the hwnd to change the text. Of course, a
button might be different with its notifications.
Quote from: MSDNThe application determines the child-window identifier
I think the number just has to be unique in your own program, not system-wide. If you create them on the fly, then use a counter like hutch said,
but if you create it you should know its ID.
Quote from: sinsi on May 14, 2009, 03:45:53 AM
I think the number just has to be unique in your own program, not system-wide. If you create them on the fly, then use a counter
Exactly. There are numerous examples that use IDOK, IDCANCEL etc as IDs for buttons. You can also reuse the IDs if you delete the old child. For example, the bookmarks in RichMasm are just child windows created (and deleted) on the fly.
Sorry I didn't make this clearer, one of my few failings. :wink
This is just a general purpose procedure to be included if and when needed, so it doesn't know what the rest of the program is going to do, like calling the function, and then going on the create a different window with the same id while the function is still running. Drat, that wasn't very clear either.
No problem, the odds are 65535 to one (or better) if I pick an obscure number, so I'm not all that worried, it would just be nice for it to never be a problem.
The createprocess function answer this with the ID.
Then ask for the terminate code and if answer is still_activ,call terminateprocess
No error handling and only barely tested:
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
include \masm32\include\masm32rt.inc
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
.data
idlist dd 65536 dup(0)
.code
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
EnumChildProc proc hWnd:DWORD, lParam:DWORD
;----------------------------------------------
; For simplicity assume the passed handle will
; always be valid and that the corresponding
; ID will always be in the range 0 to 66535.
;----------------------------------------------
invoke GetDlgCtrlID, hWnd
mov [idlist+eax*4], 1
ret
EnumChildProc endp
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
GetUniqueChildID proc hwndParent:DWORD
invoke EnumChildWindows, hwndParent, ADDR EnumChildProc, 0
;-----------------------------------------------------
; As a test, I started with an ID that I had assigned
; to the first control in the target window.
;
; Note that starting with an ID of zero will cause
; this procedure to return an ID of zero.
;-----------------------------------------------------
mov eax, 100
.WHILE eax < 65536
.IF idlist[eax*4] == 0
ret
.ENDIF
inc eax
.ENDW
xor eax, eax
ret
GetUniqueChildID endp
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
start:
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
comment |
invoke FindWindow, NULL, chr$("Button Grid Demo")
.IF eax
invoke GetUniqueChildID, eax
print ustr$(eax),13,10,13,10
.ENDIF
|
inkey "Press any key to exit..."
exit
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
end start
GetDlgItem?
var = least used id you can think of (65534)
while ( GetDlgItem(hDlg,var) != 0 )
dec var
OR
Does CreateWindow accept 0 for ID ?
OR
Can't you just show a message box "press ok to cancel"...
OR
Supply id as parameter
EDIT: CreateWindow with 0 works
Thank you everyone. Lots of things to try.
Drizz- I tried createwindow with zero, and it just died, almost immediately.
currently I'm using something very similar to your first suggestion-
CreateDownloadButton proc hWinx
local clrect:RECT
inv GetClientRect,hWinx,addr clrect
shr clrect.right,1
shr clrect.bottom,1
downloadbuttonwidth = 280
downloadbuttonheight = 60
sub clrect.right,downloadbuttonwidth/2
sub clrect.bottom,downloadbuttonheight/2
.repeat
inc dnloadid ; use a new id each time
inv GetDlgItem,hWinx,dnloadid
.until eax==0
inv GetModuleHandle,0
inv CreateWindowEx,WS_EX_TOPMOST,addr cwButton,addr opstat0,WS_CHILD or WS_VISIBLE or BS_VCENTER or BS_CENTER or BS_MULTILINE or BS_DEFPUSHBUTTON or BS_CHECKBOX or BS_PUSHLIKE ,clrect.right,clrect.bottom,downloadbuttonwidth,downloadbuttonheight,hWinx,dnloadid,eax,0
mov hDownloadCancel,eax
ret
CreateDownloadButton endp
EDIT: Sorry drizz, the zero did work. It was something else causing the problem.