News:

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

Help! Can't create a combobox

Started by NoCforMe, October 03, 2011, 06:08:49 AM

Previous topic - Next topic

NoCforMe

Hello, all: new to MASM32 (but not new to assembly language; been writing it for many years).

So I got my first "testbed" program working (creating a window). Now I want to add a combobox control to it. However, having read the applicable documentation (from MSDN), it seems that some crucial things are missing from the MASM32 package. Either that, or I'm going at this all wrong.

I'll list the problems first, then explain:
  • No support for CreateWindow (only CreateWindowEx is supported)
  • WC_COMBOBOX not defined (plus it's not clear whether this is a class-name strinmg or a numeric value)
Plus I seem to get conflicting info from MSDN as to how to create this control.

The code example on http://msdn.microsoft.com/en-us/library/hh298364%28v=VS.85%29.aspx ("How to Create a Simple Combo Box") uses CreateWindow():

HWND hWndComboBox = CreateWindow(WC_COMBOBOX, TEXT(""),
     CBS_DROPDOWN | CBS_HASSTRINGS | WS_CHILD | WS_OVERLAPPED | WS_VISIBLE,
     xpos, ypos, nwidth, nheight, hwndParent, NULL, HINST_THISCOMPONENT,
     NULL);


Now, neither CreateWindow nor WC_COMBOBOX are defined anywhere in the MASM32 package. So I tried using CreateWindowEx, which is defined.

Looking through commctrl.h (which for some reason has no counterpart in MASM32: comctrl32 contains only function prototypes), I find:

// Combobox Class Name
#define WC_COMBOBOXA            "ComboBox"
#define WC_COMBOBOXW            L"ComboBox"

#ifdef UNICODE
#define WC_COMBOBOX             WC_COMBOBOXW
#else
#define WC_COMBOBOX             WC_COMBOBOXA
#endif


from which I gather that I need to code a string with this value and pass it to CreateWindowEx() as the lpClassName parameter. Which I did, but the create call still fails (returns a NULL handle). I'm pretty sure that all the other parameters to the call are correct. (I can post my code later if needed.)

So I'm stumped. Maybe I should just ask the simple question: How do I create a combo box? (I want the kind with a static field, not the edit control.)

Thanks in advance, and thanks to the creators of this package. I've always wanted to try my hand at Windows apps, and it looks like this is the tool to do it.

ToutEnMasm


here is   sample
Quote
      .data
      xHcontrole dd 0      ;
      combobox db "COMBOBOX",0

      .code
         invoke CreateWindowEx,WS_EX_CLIENTEDGE,ADDR combobox,0,
      WS_CHILD or WS_BORDER or WS_VISIBLE or \
      CBS_HASSTRINGS or CBS_DROPDOWNLIST or WS_VSCROLL,
      startX,startY,lenght,Height,xHparente,xNumIdentifiant,xHinstance,NULL   

      mov xHcontrole,eax

NoCforMe

Thanks for the quick reply.

Still no joy. OK, here's what I have:

$CB_X EQU 50
$CB_Y EQU 50
$CBwidth EQU 100
$CBheight EQU 10
$CBID EQU 1111

.data

CBHandle HWND ?
CBclassName DB "COMBOBOX", 0

.code

INVOKE CreateWindowEx, WS_EX_CLIENTEDGE, ADDR CBclassName, NULL,
      WS_CHILD OR WS_BORDER OR WS_VISIBLE OR CBS_HASSTRINGS or CBS_DROPDOWNLIST or WS_VSCROLL,
      $CB_X, $CB_Y, $CBwidth, $CBheight, WindowHandle, $CBID, InstanceHandle, 0
MOV CBHandle, EAX


When I check the handle, it's as NULL as it can get.

I'm passing the instance handle and window handle which are correct. Should I check the result with GetLastError()?

Also, I used the values you gave, but before, I was using WS_EX_OVERLAPPEDWINDOW as the window style. (Still didn't work.)

I'm also confused by the discrepancy between your class name ("COMBOBOX") and the one from commctrl.h ("ComboBox"); maybe it's not case-sensitive?

jj2007

Normally you would do something like...

include \masm32\include\masm32rt.inc  ; make sure all important includes are there, e.g. the chr$ macro
...
CASE WM_CREATE
invoke CreateWindowEx, WS_EX_CLIENTEDGE, chr$("edit"), NULL,
WS_CHILD or WS_VISIBLE or WS_BORDER\
or ES_LEFT or ES_AUTOHSCROLL or ES_MULTILINE, 0, 0, 0, 0, ; 0, ...: will be sized later
hWnd, IdEdit, hInstance, NULL
mov hEdit, eax ; we have created an edit window

... plus a MoveWindow in the WM_SIZE handler. The only difference between CreateWindow and CreateWindowEx is the extended style; and you can use 0 to get the original behaviour of CreateWindow.

The best advice I can give is to study \masm32\examples\exampl01\generic\generic.asm
Welcome to the Forum :thumbu

NoCforMe

Thanks. But I fixed it. And it's a super-DUH! <slap forehead>

Which has to do with what you showed, putting the call to CreateWindowEx() in the processing for WM_CREATE; I had created the (parent) window after the call in my main procedure to RegisterClassEx(), with the code to create the combo box in my message handler. Of course, what happened was that the WM_CREATE message was processed before the parent window had been created, so of course it failed! Doh!

Well, I learned something today. Won't make that mistake again.

NoCforMe

OK, so I created the combo box successfully, even filled it (with the names of fonts gotten from EnumFontFamiliesEx()). I can type and the font names change, so I know they've been added to the control.

Problem is, the dropdown box doesn't drop down.

Being a newbie Win programmer, have mercy on me:

o Do I need to have all the message-handling stuff in place before I get full functionality of the combo box control? I had thought that "the system" took care of opening and closing it, but maybe not. Do I need to do any painting here?

o I'm a little confused about the general sequence of things in a Windows program, especially the proper use of WM_CREATE. Apparently, when this message is processed, the parent window hasn't yet been created, so obviously I can't use its handle. Since the comments in generic.asm say
Quote
    ; IMPORTANT, the handle for the
    ; CreateWindowEx call in the WinMain does not yet exist so the HANDLE
    ; passed to the WndProc [ hWin ] must be used here for any controls
    ; or child windows.

does that mean that I should use this "temporary" handle to create my controls? I created the combo box after the CreateWindowEx() call that created the parent window, using its handle: anything wrong with that? (Hopefully this isn't a theological, chicken-and-egg question here ...)

Also very confused by the plethora of window styles, control styles, etc. Can someone post a complete list of the attributes I need to create a simple combo box, with static (non-type-into) edit control? Just plain vanilla border styles, etc.

Do I want to use ES_AUTOHSCROLL or ES_MULTILINE? I put them in in desperation, which changed nothing.

Ghandi

I know when i've made applications with combobox i have made the mistake of not giving the control enough height to accommodate the strings i've added to it. I have also forgotten to give it the WS_VSCROLL style which meant that when the added strings exceeded the height of the drop down portion they would disappear below sight.

HR,
Ghandi

NoCforMe

Doh! #2. I thought the height parameter was the height of the closed control. It's the height of the opened box!

See, this is what you get when you try to learn Win programming without a proper book. It's like shooting in the dark. MSDN is not the right place to learn the basics.

Thanks for the tip.

dedndave

i am a little surprised to see that CreateWindow is not supported in the masm32 package user32.inc file - lol
i guess it's because there is little need for the function
it's probably just a wrapper for CreateWindowEx, anyways
the only parameter not included is the extended style - not like it saves a lot of work   :P
if you want to use it, all you need is a prototype (or 2)
you can put them in an include file or at the beginning of your source
or, simply add them to the existing user32.inc file
that's probably the best way, but you have an issue of compatibility with other forum members when you do that

CreateWindowA PROTO :DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD
CreateWindow equ <CreateWindowA>
CreateWindowW PROTO :DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD

it might be more correct to properly type all the parms in the prototypes
but the end results will be the same

as for adding it to the WM_CREATE code, you will find that it is a great place to do many things
it does not come without some caveats, however
a few things are better left out of WM_CREATE - you will find them, in time
an example does not come to mind at the moment, but i have experienced this
another problem may arise if you use the same WndProc for more than one window
you may have to test the hWnd value passed to WndProc and the one stored globally to ensure it isn't called twice

MichaelW

From WinUser.h in the PSDK:

#define CreateWindowA(lpClassName, lpWindowName, dwStyle, x, y,\
nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam)\
CreateWindowExA(0L, lpClassName, lpWindowName, dwStyle, x, y,\
nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam)

#define CreateWindowW(lpClassName, lpWindowName, dwStyle, x, y,\
nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam)\
CreateWindowExW(0L, lpClassName, lpWindowName, dwStyle, x, y,\
nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam)


And CreateWindowA and CreateWindowW are not listed in the exports for the Windows 2000 user32.dll.
eschew obfuscation

NoCforMe

Already this is turning out to be a good learning experience.

In addition to the two "Doh!"s, I also discovered that the class name passed to CreateWindowEx() (COMBOBOX in this case) is handled in a case-insensitive manner. "ComboBox" works fine, as does "cOmBoBoX".

Quote from: MichaelW on October 03, 2011, 01:57:36 PM
And CreateWindowA and CreateWindowW are not listed in the exports for the Windows 2000 user32.dll.

This raises the question: how does one know which functions to use, which ones are actually supported by which versions of Windows, which ones have been obsoleted, etc? The MSDN documentation is of some help here, but with limits. (In some case, it does explicitly mention that a function is obsolete, such as those used for 16-bit Windows programming.)

And how does one get an export report? Is there some way to generate a list of all available functions within a running copy of Windows? some other way of doing this?

Also, you'll notice that I'm going off on a tangent here, which is intentional, as I'd like to know how well this tolerated here (I'm new in town), and whether I should create a new thread for these questions.

jj2007

Quote from: NoCforMe on October 03, 2011, 06:44:11 PM
Is there some way to generate a list of all available functions

You can have a list of all functions included in the Masm32 package...

Analysing 344 files took 406 ms - 54148 PROTOs found
Written to MyProtos.txt

### \masm32\include\1394bus.inc
Bus1394RegisterPortDriver@1
### \masm32\include\acledit.inc
DllMain@3
FMExtensionProcW@3
SedDiscretionaryAclEditor@13
SedSystemAclEditor@12
SedTakeOwnership@14
### \masm32\include\aclui.inc
CreateSecurityPage@1
EditSecurity@2
### \masm32\include\acpisim.inc
AcpisimAddDevice@2
AcpisimClearDevExtFlags@2
AcpisimCompleteSIrp@5
...


Source:
include \masm32\MasmBasic\MasmBasic.inc   ; Download
   Init
   MaxLines=100000
[/color]   push Timer
   Dim
Proto$(MaxLines)
   xor edi, edi
   GetFiles
\masm32\include\*.inc
   For_ ebx=0 To eax-1
      Let Proto$(edi)="### "+Files$(ebx)
      inc edi
      Recall Files$(ebx), Inc$()   ; load all strings into an array
      For_
ecx=0 To eax-1
         Let esi=Inc$(ecx)
         .if Instr_(esi, "PROTO")
            push ecx
            push ebx
            push edx
            or ebx, -1
            .Repeat
                  inc edx
                  inc ebx
            .Until !Instr_(edx, esi, ":")
            pop ecx
            Let Proto$(edi)=Left$(esi, ecx-2)+Str$("@%i", ebx)
            pop ebx
            
pop ecx
            inc edi
            .Break .if edi>=MaxLines
         .endif
      Next
      .Break .if edi>=MaxLines
   Next
   Print Str$("Analysing %i files", ebx)
   pop ecx
   Print Str$(" took %i ms - ", Timer-ecx), Str$("%i PROTOs found\n", edi-ebx)
   Store "MyProtos.txt", Proto$(), edi   ; write edi strings to file
   Inkey "Written to MyProtos.txt"
   Exit
end start


By the way, I have an older Masm32 installation on a different drive, dated January 2008, with half as many PROTOs. Hutch is not as lazy as it seems :green2

MichaelW

Quote from: NoCforMe on October 03, 2011, 06:44:11 PM
This raises the question: how does one know which functions to use, which ones are actually supported by which versions of Windows, which ones have been obsoleted, etc?

You could just select the function that will do what you need to do, and if it's not supported then depending on how you are linking the function you will get an error from the linker or from the OS at load time or run time.

Quote
And how does one get an export report?

One quick and dirty method that will usually work is to simply open the DLL in a text editor and look at the names. Or you could use the Microsoft COFF Binary File Dumper, dumpbin.exe, located in the MASM32\bin directory.


eschew obfuscation