Creating multiple windows using for loop

Hi, I am trying to create a number of static controls (and, soon, edit controls as well) in a window. The number is to be determined at runtime. I use an int as the HMENU item in order to create indefinitely many control handles. Oddly, in my test case of five, all static controls are created, but only two (0 and 4) have the desired text sent to them. The error returned on the failed SendMessages is ERROR_INVALID_WINDOW_HANDLE.

(I start at the HMENU ints at 100000 in the hope that this would avoid clashing with any reserved ints, if there are any such. For what it is worth, my current suspicion is that there are and I failed to avoid them...)

How should I do what I am attempting to do?

Any help appreciated :)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
typedef std::basic_string<TCHAR> tstring;

...

case WM_CREATE:
{
RECT rect;
GetClientRect(hwnd,&rect);
int count=0;
int max=wf.dag.getMaxVals().first;
tstring text;
while (count<max)
{
CreateWindowEx(NULL,_T("STATIC"),NULL,WS_CHILD|WS_VISIBLE,10,count*25,rect.right-20,20,hwnd,(HMENU)100000+count,GetModuleHandle(NULL),NULL);
ShowWindow(GetDlgItem(hwnd,100000+count),SW_SHOW);
text=_T("Value: ")+num2T(count);
SendMessage(GetDlgItem(hwnd,100000+count),WM_SETTEXT,0,(LPARAM)text.c_str());	
EnableWindow(GetDlgItem(hwnd,100000+count),FALSE);
++count;
}
break;
I have arrived at a solution of a sort: Declaring a defined number of strings on my string table and having only this many child windows on the page at one time, then using "Next Page", "Last Page" buttons to cycle through however many come to be needed at run-time. (OK - its less of a solution than avoiding the problem...)
It almost makes me groan to see such horribly inefficient code. The lParam of the WM_CREATE message will give you the HINSTANCE you need when cast properly to a CREATESTRUCT. You don't need to keep calling GetModuleHandle in a loop no less!

You are doing the same thing in failing to save the returned HWND from your CreateWindow() calls and then calling SendMessage() to get the HWND that was just returned to you but you disgarded!!!
Here is what I came up with just with buttons (sorry - no UNICODE. Just did it simple with GNU). I ran into the four times table problem too. Had to create a seperate variable. Don't know what's going on there...some kind of C++ funk....

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
//Main.cpp
#include <windows.h>
#include <stdio.h>
#include "LoopChilds.h"
EVENTHANDLER  EventHandler[3];


long fnWndProc_OnCreate(lpWndEventArgs Wea)
{
 char szButtons[16],szNumber[8];
 DWORD dwCtrlId;
 HWND hCtrl;

 Wea->hIns=((LPCREATESTRUCT)Wea->lParam)->hInstance;
 for(unsigned int i=0; i<5; i++)
 {
     strcpy(szButtons,"Button #");
     sprintf(szNumber,"%u",i+1);
     strcat(szButtons,szNumber);
     dwCtrlId=2000+i;
     hCtrl=CreateWindowEx(0,"button",szButtons,WS_CHILD|WS_VISIBLE,85,i*40+30,120,25,Wea->hWnd,(HMENU)dwCtrlId,Wea->hIns,0);
 }

 return 0;
}


long fnWndProc_OnCommand(lpWndEventArgs Wea)
{
 char szMessage[32], szNumber[8];
 unsigned int iCtlId;

 iCtlId=LOWORD(Wea->wParam);
 if(iCtlId>=IDC_BUTTON && iCtlId<=IDC_BUTTON+4)
 {
    strcpy(szMessage,"You Clicked Button #");
    sprintf(szNumber,"%u",iCtlId-IDC_BUTTON+1);
    strcat(szMessage,szNumber);
    MessageBox(Wea->hWnd,szMessage,"Button Click Report",MB_OK);
 }

 return 0;
}


long fnWndProc_OnClose(lpWndEventArgs Wea)
{
 DestroyWindow(Wea->hWnd);
 PostQuitMessage(0);

 return 0;
}


void AttachEventHandlers(void)
{
 EventHandler[0].Code=WM_CREATE,      EventHandler[0].fnPtr=fnWndProc_OnCreate;
 EventHandler[1].Code=WM_COMMAND,     EventHandler[1].fnPtr=fnWndProc_OnCommand;
 EventHandler[2].Code=WM_CLOSE,       EventHandler[2].fnPtr=fnWndProc_OnClose;
}


long __stdcall fnWndProc(HWND hwnd, unsigned int msg, WPARAM wParam,LPARAM lParam)
{
 WndEventArgs Wea;

 for(unsigned int i=0; i<3; i++)
 {
     if(EventHandler[i].Code==msg)
     {
        Wea.hWnd=hwnd, Wea.lParam=lParam, Wea.wParam=wParam;
        return (*EventHandler[i].fnPtr)(&Wea);
     }
 }

 return (DefWindowProc(hwnd, msg, wParam, lParam));
}


int __stdcall WinMain(HINSTANCE hIns, HINSTANCE hPrevIns, LPSTR lpszArgument, int iShow)
{
 char szClassName[]="LoopChilds";
 WNDCLASSEX wc;
 MSG messages;
 HWND hWnd;

 AttachEventHandlers();
 wc.lpszClassName=szClassName,               wc.lpfnWndProc=fnWndProc;
 wc.cbSize=sizeof (WNDCLASSEX),              wc.style=CS_DBLCLKS;
 wc.hIcon=LoadIcon(NULL,IDI_APPLICATION),    wc.hInstance=hIns;
 wc.hIconSm=LoadIcon(NULL, IDI_APPLICATION), wc.hCursor=LoadCursor(NULL,IDC_ARROW);
 wc.hbrBackground=(HBRUSH)COLOR_BTNSHADOW,   wc.cbWndExtra=0;
 wc.cbClsExtra=0,                            wc.lpszMenuName=NULL;
 RegisterClassEx(&wc);
 hWnd=CreateWindowEx(0,szClassName,"Loopy Buttons",WS_OVERLAPPEDWINDOW,100,100,300,290,HWND_DESKTOP,0,hIns,0);
 ShowWindow(hWnd,iShow);
 while(GetMessage(&messages,NULL,0,0))
 {
       TranslateMessage(&messages);
       DispatchMessage(&messages);
 }

 return messages.wParam;
}



And LoopChilds.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//LoopChilds.h
#define  IDC_BUTTON    2000

typedef struct         WindowsEventArguments
{
 HWND                  hWnd;
 WPARAM                wParam;
 LPARAM                lParam;
 HINSTANCE             hIns;
}WndEventArgs,         *lpWndEventArgs;


struct EVENTHANDLER
{
 unsigned int          Code;
 long                  (*fnPtr)(lpWndEventArgs);
};
Last edited on
Ha! Just dawned on me out of the blue! The HMENU four times table thing. Its afterall a virtual memory handle thing with pointers, so when you increment it by i in a loop you get pointer arithmetic, i.e +4 for 32 bit OS.

I do this all the time in another programming language and it doesn't happen there. So with C/C++ you indeed do need a seperate proxy variable, so to speak.
Topic archived. No new replies allowed.