![]() |
| | #1 |
| Registered User Join Date: Oct 2008
Posts: 27
| I am having a bit of a headache trying to structure my program "the right way". This is the case: I am making a dynamic link library, containing some resources and functions that will allow me to open a window, throw a skin on it, pass in some value from the calling language and then return. Then I will poll from the calling language to see if the window is closed, and return either a manipulated version of the value that was passed in, or a value indicating which button was pressed (message box for instance) and so on, depending on what purpose the window opened had. The way I am trying to do things are: I have a main source file + header that defines the export functions visible to the calling language. I have one source file + header which defines a class for the skinning process. I have one source file + header which defines the common functions for a window, mainly;
I have a source file + header for each of my custom controls (they are not using classes, atm (old style C with structures, and so on)) And finally I have a source file + header for each of my different windows. Now, it shall be possible for some of my windows to have multiple instances open at the same time, so the way I was trying to go about that was to create an instance of my classes in the DLL export function and put them inside a structure, because I am spawning a new thread for each call to my window. The process goes something like this:
Now the function CreateThread is calling is just a wrapper that calls a WinMain-style function, with an additional parameter; the pointer to my structure with the class pointers. Inside my WinMain-style function for my window, the following takes place:
Is this a good way to do it? I am not sure if it will work at all... I am not deleting my classes now, for instance, I am not sure how to go about doing that. I also have to return the window handle to my calling language, in some way, so that I have a way of polling the right window for results, and also for doing cleanup on exit. The way I initially was intending to do this was to have a class for each window too (would solve some of my cleaning up problems by using the destructor), but I ran into some paradoxes with the callback procedure not being static, and if I were to define it as static, i would run into problems with my pointers to the skin class inside the static function, and so on. Also, I was experiencing some trouble with accessing my resources. It seemed like the calling language did not load the DLL the way I expected. I found a way to "solve" this by calling LoadLibrary("mydll.dll") from my DLL. Not sure if this is very nice to do either. Now, do you guys have any suggestions and advices on how to do this the most elegant, and smooth way? Feel free to flame and yell at me for not doing my homework and coming up with stupid ideas :-) I deserve it :-) Last edited by Eirik; 04-27-2009 at 05:55 AM. Reason: More descriptive title |
| Eirik is offline | |
| | #2 |
| Registered User Join Date: Sep 2004 Location: California
Posts: 2,845
| Why are you creating multiple threads for this? It seems like a very bad idea. All window handling code should be done in the main message loop thread. |
| bithub is offline | |
| | #3 | |
| Registered User Join Date: Oct 2008
Posts: 27
| Quote:
| |
| Eirik is offline | |
| | #4 |
| Registered User Join Date: Sep 2004 Location: California
Posts: 2,845
| No you wont. Windows do not block, they simply return to the message loop. If your window is blocking, chances are you are creating it incorrectly. |
| bithub is offline | |
| | #5 |
| Registered User Join Date: Oct 2008
Posts: 27
| Hmm.. I am creating it like this: Code: int APIENTRY MyWin(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPTSTR lpCmdLine,int nCmdShow) {
WNDCLASSEX wcex;
HBRUSH hbrGray;
MSG msg;
hbrGray = CreateSolidBrush(RGB(216,216,216));
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = NULL;
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = hbrGray;
wcex.lpszMenuName = NULL;
wcex.lpszClassName = "myWndClass";
wcex.hIconSm = NULL;
wcex.cbWndExtra = 0;
RegisterClassEx(&wcex);
HWND hwnd = CreateWindowEx(WS_EX_TOPMOST | WS_EX_TOOLWINDOW,
"myWndClass",
"Nice title",
WS_OVERLAPPEDWINDOW,
200,
200,
190,
335,
NULL,
NULL,
hInstance,
NULL);
ShowWindow(hwnd,nCmdShow);
UpdateWindow(hwnd;
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
UnregisterClass("myWndClass",GetModuleHandle(0));
return (int) msg.wParam;
}
Note that this code resides in a DLL that the calling language is opening, and then executing. It is not a regular executable file. Last edited by Eirik; 04-28-2009 at 11:56 AM. |
| Eirik is offline | |
| | #6 |
| Senior software engineer Join Date: Mar 2007 Location: Portland, OR
Posts: 5,381
| If your DLL is called by an application, then it can't have a message loop. There must be only one message loop in the application. Things might be simpler if you register your window as a dialog instead of an application window.
__________________ "Congratulations on your purchase. To begin using your quantum computer, set the power switch to both off and on simultaneously." -- raftpeople@slashdot |
| brewbuck is online now | |
| | #7 |
| Registered User Join Date: Sep 2004 Location: California
Posts: 2,845
| If you don't want to use a dialog window, then your DLL should call SetWindowsHookEx() to set a WH_GETMESSAGE hook. This will allow your DLL to get the window messages from the main message pump so that you can update your own windows. |
| bithub is offline | |
| | #8 |
| Hat seller extraordinaire Join Date: Apr 2008
Posts: 159
| Since when?
__________________ Desktop Heap Monitor for Vista/7 A solution to Visual Studio 2005/8 runtime problems Getting Kernel Thread Call Stacks Last edited by adeyblue; 04-28-2009 at 03:38 PM. |
| adeyblue is offline | |
| | #9 |
| Registered User Join Date: Sep 2004 Location: California
Posts: 2,845
| |
| bithub is offline | |
| | #10 |
| Senior software engineer Join Date: Mar 2007 Location: Portland, OR
Posts: 5,381
| Since programmers decided to maintain their sanity?
__________________ "Congratulations on your purchase. To begin using your quantum computer, set the power switch to both off and on simultaneously." -- raftpeople@slashdot |
| brewbuck is online now | |
| | #11 |
| Unregistered User Join Date: Jul 2007
Posts: 925
| I think adeyblue just misunderstood brewbuck; What brewbuck really meant (I think) is that there's only ever one active message loop in a program. If you do have multiple msg loops, they're always exchanging control so that only one is actually running at a time.
__________________ GCC 4.4.0, Code::Blocks 8.02, Fedora 11, x64 |
| Yarin is offline | |
| | #12 | |
| Registered User Join Date: Oct 2008
Posts: 27
| Quote:
Another obstacle I'm running into here is this: I register my window specifiing some extra bytes at the cbWndExtra member, like this: Code: wcex.cbWndExtra = sizeof(CSkin *) + sizeof(CWindowData *); In my window procedure I have this code: Code: LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
CWindowData *cwp = (CWindowData *)GetClassPointer(hwnd,0);
CSkin *csp = (CSkin *)GetClassPointer(hwnd,sizeof(CWindowData *));
if(csp->IsHandledMessage(message)) // Is there any messages that needs to be trapped for the skinning process?
return csp->WndProc(hwnd,message,wParam,lParam);
Code: cwp = new CWindowData(); csp = new CSkin(); SetClassPointer(hwnd,cwp,0); SetClassPointer(hwnd,csp,sizeof(CWindowData *)); Any suggestions how I should go about doing this? The skin class is depending on processing some early messages sent to the window, like WM_GETMINMAXINFO and WM_NCCALCSIZE. | |
| Eirik is offline | |
| | #13 |
| Unregistered User Join Date: Jul 2007
Posts: 925
| >> I register my window specifying some extra bytes at the cbWndExtra member, like this: The problem though, is you're reading the window's class bytes. (e.g cbClsExtra, not cbWndExtra). To alter the window's values you should use GetWindowLong. >> What excactly will happen then? Will I receive, say, a WM_ACTIVATE notification to my window if I activate the parent window? No. Your hook will receive the same messages that your thread's windows receive. The hook's proc runs separately from the running msg loop.
__________________ GCC 4.4.0, Code::Blocks 8.02, Fedora 11, x64 |
| Yarin is offline | |
| | #14 | |
| Registered User Join Date: Oct 2008
Posts: 27
| Quote:
| |
| Eirik is offline | |
| | #15 |
| Unregistered User Join Date: Jul 2007
Posts: 925
| Right. Sorry about that. What I would do is this: -> Create the window initially invisible. -> Tell your WndProc to just return zero on the WM_CREATE and WM_NCCREATE messages. -> Call that SetClassPointer chunk of code you have there. -> Send a custom WM_USER message to your window. In the handler for this message, you would have everything that you previously had in the WM_CREATE case. This is were you would also then make the window visible and active using ShowWindow.
__________________ GCC 4.4.0, Code::Blocks 8.02, Fedora 11, x64 |
| Yarin is offline | |
![]() |
| Tags |
| c++, class, pointer, windows |
| Thread Tools | |
| Display Modes | |
|
Similar Threads | ||||
| Thread | Thread Starter | Forum | Replies | Last Post |
| Terrible confusion with time variables | LowlyIntern | C++ Programming | 12 | 08-01-2008 07:23 AM |
| C++ Classes: Use, Misuse...Confusion. | Snorpy_Py | C++ Programming | 4 | 10-23-2006 01:46 AM |
| for loop confusion | Enges | C++ Programming | 6 | 04-26-2006 08:21 AM |
| Server-net newbie confusion | geek@02 | Windows Programming | 1 | 04-28-2005 02:08 AM |
| confusion with increment and decrement operators | cBegginer | C Programming | 6 | 03-19-2005 03:45 PM |