News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Getting a unique window id

Started by Jimg, May 14, 2009, 12:24:37 AM

Previous topic - Next topic

Jimg

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.

hutch--

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.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

Jimg

Thanks Hutch.  It sure would have been nice if createwindow would have returned an error if there was a duplicate!

sinsi

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.
Light travels faster than sound, that's why some people seem bright until you hear them.

jj2007

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.

Jimg

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.

ToutEnMasm


The createprocess function answer this with the ID.
Then ask for the terminate code and if answer is still_activ,call terminateprocess


MichaelW

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

eschew obfuscation

drizz

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
The truth cannot be learned ... it can only be recognized.

Jimg

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.