Click to See Complete Forum and Search --> : basic win(nonMFC) coding theory..?


April 16th, 1999, 01:29 AM
Just starting to do some non mfc, win32 api programming. Right away the basic problem comes up, what is the best way to get a specific data pointer into a window procedure, i.e. associate data with a specific window? Ive been using lots of globals to hold my data, but this will only allow one instance of the window to work at a time.

How does MFC do it? I see two ways.. make some global mapping object, that will take a specific hwnd, and return a pointer to its data, or store a pointer to data "in" the window using SetWindowLong()... Then at the start of the window procedure, you will access this pointer.

Hope I explained it clearly enough, thanks

Jason Teagle
April 16th, 1999, 02:40 AM
When you create the WNDCLASS for your window, you can get the API to allocate extra space with each window. This is done as follows:

In header file:
---
typedef struct tagMyWindowData
{
int iData1 ;
DWORD dwData2 ;
etc.

} MY_WINDOW_DATA ;


---

In code file:
---
WNDCLASS sWC ;

sWC.style = CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS ;
sWC.lpfnWndProc = MyWindowProcedure ;
sWC.cbClsExtra = 0 ; // If you want to store data that applies to ALL
// instances of this type of window, make this
// value greater than 0.
sWC.cbWndExtra = 1 ; // 1 LONG. Sufficient for an HGLOBAL.
etc.

RegisterClass(&sWC);


---

Basically we have allowed sufficient space with each instance of window of this class for a HANDLE TO A LUMP OF MEMORY which will hold a structure of type MY_WINDOW_DATA, which would contain all of the data you want to associate with the window. Whenever you want to manipulate data for this window, use this to access the structure:

---
HGLOBAL hMem ;
MY_WINDOW_DATA *psMWD ;

// We have stored one pointer, starting at offset 0 (of the extra window
// data). This offset (0) is the second parameter here:
hMem = (HGLOBAL)GetWindowLong(hMyWnd, 0);
psMWD = (MY_WINDOW_DATA *)GlobalLock(hMem);

// Now we can manipulate the data within the structure.

GlobalUnlock(hMem); // As we locked it, we must unlock it afterwards.


---

To set the value in the extra space initially (after creating each window instance), use:

---
HGLOBAL hMem ;
MY_WINDOW_DATA *psMWD ;

hMem = GlobalAlloc(GHND, sizeof(MY_WINDOW_DATA) );
psMWD = (MY_WINDOW_DATA *)GlobalLock(hMem);
// Set initial data here...
GlobalUnlock(hMem); // As we locked, unlock.

SetWindowLong(hMyWnd, 0,(LONG)hMem);


---

Don't forget to call GlobalFree() on the memory lump in the WM_DESTROY message, to prevent memory leaks.

Of course, you could skip the global memory thing and just store the pointer directly into the extra space with the window instead of the HGLOBAL.

I have to ask, though, why use the API directly instead of MFC? It's like trying to hammer a nail in with your thumb instead of a hammer. If you can, I highly recommend using MFC.

If you want any further help, I can be reached at jteagle@solartron.com

April 16th, 1999, 04:31 PM
I see! thank you. Partly I just want to understand "raw" windows programming, and also the giant mfc dlls are really too much for what Im doing, so no MFC.

thanks, rj

Alvaro
April 16th, 1999, 06:22 PM
The way computer hardware prices are falling these days, I wouldn't worry too much about bloated DLLs: after all that's what Microsoft promotes :-)

But seriously, I just took a simple MFC app which only displays a couple of dialog boxes and built it using MFC statically and MFC in a shared DLL. Here are the sizes of the files you'd need to run it:


MFC in a shared DLL:
--------------------
App.exe 33 K
MFC42.dll 995 K
MSVCRT.dll 266 K
------
1294 K


MFC in a static library:
------------------------
App.exe 238 K
------
238 K




What does that tell you? I guess what I'm trying to prove is that one way to get the best of both worlds, quick and easy development with MFC plus a small/efficient executable is to link with MFC statically. It defeats the purpose of DLLs but the time/headaches you save in development are well worth it!

That's my 2 cents.


Alvaro

Todd Jeffreys
April 16th, 1999, 08:27 PM
The cbWndExtra member in WNDCLASSEX is in bytes. So if you wanted to add a long value, you'd have to set that to 4 (since long = 4 bytes). For Win95/98 The max cbWndExtra value is 40, for roughly 10 32 variables. I think NT is unlimited. I do a lot of Win32 stuff and that's how i store things

Jason Teagle
April 19th, 1999, 02:32 AM
Another advantage to statically linking MFC is to do with version numbers; have you ever encountered the horrid "Can't find ordinal XX in MFCXX.DLL" error? Basically, some program somehow manages to install an older version of the MFC DLL on your system, and a program which requires a newer version goes belly-up. If you statically link, then yes, it defeats the object of DLLs - but it is a much more reliable method, and requires fewer distribution files to boot.

Microsoft themselves have defeated the idea of DLLs by releasing multiple versions of DLLs with the same name. For a DLL as widely-shared and important as fundamental MFC stuff, they should have the sense to distinguish between them somehow.

Paul McKenzie
April 19th, 1999, 03:37 AM
I couldn't agree more. Everything is statically linked here. I would NEVER ship an MFC application that relies on the MFC DLL's on a customer's machine. No way, no how!

I still don't wish to know the umpteen MFC DLL's I need to ship an MFC app that links dynamically :-()


Regards,

Paul McKenzie