   The Greatest Win32 Post There Ever Was...
  Okay, maybe a *little* over the top there...I have made several posts about Windows programming in the last month, all dancing around a couple of different subject areas. And while I always appreciate *anybody* who takes the time to try and answer the questions I post, I just haven't been getting the answers I'm looking for.So I'm going to start from the top, cross my fingers, close my eyes and pray.There are many great introductory guides to Windows Programming:winprog.org/tutorial/www.geocities.com/Heartland/Meadows/9818/win32tut/index.htmlwww.functionx.com/win32/index.htmIn addition, eventually I will purchase a copy of Petzold's "Programming Windows," a several thousand-page tome on the subject. But I just graduated and alas, I am broke. ("Get a job already!" I hear my parents screaming somewhere off in the distance. :-) )But all these guides, as good as they are, are not interactive. So if they fail to mention something important, something that an expert on the matter (like the authors) might overlook, it's rather difficult for me to get an answer. Such is the nature of this post.I am stuck with two areas of my fairly simple Windows program:(a) Child controls, buttons, list boxes, edits, etc.(b) DialogsSo what I will do is tell you all about what I think is the correct way to set these up, and then I'll let you tear my theories apart and tell me what to go do with myself ;-). Then afterwards, maybe, you can point me in the right direction(s).MY THEORIES ON WINDOWS CHILD CONTROLS AND DIALOGS, AND WHAT NOT:(1) All "controls" are really just interactive Windows, like the main Window of your application; just sub-classed and specialized to perform certain functions.(2a) Every control has a UINT "resource" identifier associated with it, so that when a WindProc receives a message that, say, a button has been pressed, it can identify which button control fired that event.(2b) These resource IDs are created magically from a mystical geiser located somewhere in Antarctica that spews them out about every half hour. The programmer needs only to capture these IDs as they are cast out into the open air, but never has to worry about how they are generated or otherwise made.(3) Making a "Hello, Dialogs!" dialog (not a system dialog or a MessageBox) pop up when the main WindProc receives, say, a WM_CREATE message is as easy as the following:(i) Cut a hole in the box...(ii) Put your... never mind(iii) Inside WindProc:case WM_CREATE:    SayHelloToMy1stDialog();    // Do lots of other stuff...    break;// Now waaaaay down, somewhere in the main.cpp file:void SayHelloToMy1stDialog(){    // helloDialog is a global HWND.    LPTSTR dlgID = captureIDFromMagicGeyser(Locale::ANTARCTICA);    helloDialog = CreateDialog(hInstance, dlgID, hwnd, HelloDlgWindProc);    // Now magically draw it to screen, wooo!    helloDialog.show();}// Also inside main.cpp somewhere, helloDialog's WindProc:LRESULT CALLBACK HelloDlgWindProc(HWND hwnd, UINT msg, WPARAM w, LPARAM l){    UINT magic_resource_id = captureIDFromMagicGeyser(Locale::ANTARCTICA);    switch(msg)    {   case BN_CLICKED:    // Or WM_COMMAND????  switch(magic_resource_id)  { case IDB_MY_1ST_BUTTON:DoSomething();break; default:DoSomethingElse();break;  }  break;   default:  DefDlgProc();  break;    }}(4) Windows operate according to a hierarchy, much like Java has a container hierarchy of windows, frames, panels, etc. The Windows paradigm is as follows:Window > Dialog > Control.(5) The difference between a bona fide Windows message, such as WM_DESTROY, and a notification, such as BN_CLICKED, is that Windows Messages get handled in window procedures, and notifications are fed to hungry lions living at the bottom of the system freestore.(6) There is no difference between a macro and a function.Thanks for any help and all your time here guy! And gals. People.plywood   
Quote:In addition, eventually I will purchase a copy of Petzold's "Programming Windows," a several thousand-page tome on the subject. But I just graduated and alas, I am broke.Libraries don't charge to borrow books...  Around here you can check them out for a month at a time and renew indefinitely unless somebody else put a hold on it.Windows, dialogs, and controls are all the same thing - windows.  "Control" is generally meant to be a window that is a child of another window and not a dialog.  "Dialog" is generally meant to mean a "popup" window that can be a child of another window.  Dialogs also have various normal behaviors that Windows (the OS) handily supplies for you via the DialogBox family of functions.Resource/window id's are defined by you, the programmer.  You can set them to whatever you want.  It's generally useful if you don't assign the same id to two different things."Notifications" are exactly the same as "bona fide Windows messages".  I suppose you can think of notifications are sub-messages in that they are usually received via a WM_COMMAND or WM_NOTIFY message.There's a vast difference between a macro and function.   ;  1) Close but not quite.  Controls are a type of window.  Dialogs are a type of window.  You are right there.  However they aren't necessarily sub classed.  Let's consider a button a class of window.  It has a specific window procedure that ALL windows of the button class use.  When you create a window of the button class, and change it's window procedure (using SetWindowLongPtr), you are sub classing that window, and that window only.  Prior to this, the window wasn't subclassed, it just used the window procedure that the button class processes its messages with.2) They way you stated the rest of your post, I'm assuming your talking about controls generated by way of your local resource editor?  Visual Studio or whatever you're using generates these IDs.  Look in resource.h.  You can change them.  If they were located in some far off land this would be a bit more difficult.3) The best I can say is that "captureIDFromMagicGeyser(Locale::ANTARCTICA);" being replaced with the constant defined in resource.h (assuming you generated this dialog box with your resource editor) would make number 3.... more accurate, though maybe not perfect.  Remember when you created that dialog box in the first place in your resource editor?  Visual Studio automatically inserted a unique ID for it in that file.  This kept you from having to figure out one that hadn't been used yet, and is arguable considered a feature.4) More like Window->Window->Window->Window.  MFC for instance uses some confounded mainframe->frame->view->control (or something)... but these are all windows.  Call them whatever you want if it makes sense in your design :)5) Msdn explains that to process bn_clicked, you get the WM_COMMAND message (which is handled by your windows procedure) and the BN_CLICKED is discovered by getting the upper 16 bits of wParam (essentially chopping your lion in half to figure out what the notification it ate IS, exactly).  Note that googling "BN_CLICKED" brought this up as the first entry.6) Whoa.  Needless to say that's incorrect.  And it's not just a slight difference so I don't know where to start.Cheers-Scott   ;Quote:Original post by plywoodMY THEORIES ON WINDOWS CHILD CONTROLS AND DIALOGS, AND WHAT NOT:(1) All "controls" are really just interactive Windows, like the main Window of your application; just sub-classed and specialized to perform certain functions.You're right that they're just special Windows, that each perform a certain function.  They're a little different from your main window in that controls must always be the child of another window, while your main window typically has no parent.  They're also not sub-classes by default...sub-classing a window is when you tell the OS "instead of sending this window messages directly, send them to my function first".  So if you sub-class a control, you'll get a chance to intercept its messages before the control handles them. It's typically used to add new functionality to a control.Original post by plywood(2a) Every control has a UINT "resource" identifier associated with it, so that when a WindProc receives a message that, say, a button has been pressed, it can identify which button control fired that event.Uh huh, that's how it works.Quote:Original post by plywood(2b) These resource IDs are created magically from a mystical geiser located somewhere in Antarctica that spews them out about every half hour. The programmer needs only to capture these IDs as they are cast out into the open air, but never has to worry about how they are generated or otherwise made.No no no.  Control ID's are explictly defined by you.  See there's two common ways to create a control:  by calling CreateWindow and specifying the name of control's window class, or by adding the control to a dialog template (usually via the Visual Studio Dialog Editor).  If you create a control using CreateWindow, you specify the ID via the hMenu parameter.  If you add the control to to a dialog template, the ID is one of the properties you can edit (you actually specify a name, like BTN_OK and the resource editor will assign it a number.  It will also generate a header file with those ID's as constants, so you can just use BTN_OK in your code).Quote:Original post by plywood(3) Making a "Hello, Dialogs!" dialog (not a system dialog or a MessageBox) pop up when the main WindProc receives, say, a WM_CREATE message is as easy as the following:(i) Cut a hole in the box...(ii) Put your... never mind(iii) Inside WindProc:*** Source Snippet Removed ***Resource ID's are different from control ID's, and I think you're confusing them a bit here.  A resource ID is a unique integer that identifies anything added to the program's resource project.  Typically it's what you use to load an icon as a resource, or a dialog template.  They are assigned much the same way if you're using Visual Studio's resource editor, in that you'll name the resource with a string and VS will map it to an integer for you.Quote:Original post by plywood(4) Windows operate according to a hierarchy, much like Java has a container hierarchy of windows, frames, panels, etc. The Windows paradigm is as follows:Window > Dialog > Control.There's definitely a hierarchy, but it's not based on dialog's and controls (although like I said controls are always child windows, and therefore are often children of windows and dialogs).  Instead you have two relationships between windows:  child/parent and owner/owned window.  Owned windows are created by using CreateWindow and specifying the handle of the owner window as the hWndParent parameter.  Owned windows will appear in front of their owners, and won't receive their own entry in the taskbar.  Dialogs are typically created as owned windows (although they don't have to be).  One important characteristic of owned windows is that if a modal dialog is created, all of its owners are disabled until the dialog exits.Child windows on the other hand are "always inside" their parent window.  If they're moved, they'll be clipped at the edge of their parent.  This makes sense for controls, since you'd never want to have something like a button appear outside the parent window.  Child windows are created by using CreateWindow and specifying an owner, and also specifying the WS_CHILD style.See the sections "Child Windows" and "Owned Windows" in the documentation for more info.Quote:Original post by plywood(5) The difference between a bona fide Windows message, such as WM_DESTROY, and a notification, such as BN_CLICKED, is that Windows Messages get handled in window procedures, and notifications are fed to hungry lions living at the bottom of the system freestore.No they're both handled the same exact way.  They're both messages, notifications are just called that when they're sent as a response to an event.  For example, WM_DESTROY is a notification because it's sent in response to your window being destroyed as a result of DestroyWindow being called or the user closing the window.Quote:Original post by plywood(6) There is no difference between a macro and a function.No there's a huge difference.  Macros literally just fill in code wherever they're used.  Take this for instance:#define DO_SOMETHING() { num = 0 }void func1(){    int num;    DO_SOMETHING();}void func2(){    DO_SOMETHING();}In this simple example, func1 will compile and func2 won't.;  6) (since other poster failed to answer it)A macro has NOTHING to do with windows programming perse, it is just a way to make your life (arguably) easier. It is not a function (though it can be similar to one).A macro is a preprocessor directive. you can look at it kinda like a 2 step process during compilation (there is more too it, but this will help rationalize it). Anyhow, the first parse goes through and turns all your macros (defines) into actual code. Its more like a find/replace or an embedded procedural language. before the actualy compilation occures, the macros are transformed into meaningfull code counterparts, which is THEN compiled. Macros are not necessaraly cross platform, but are often used to hide cross platform issues or simplify porting (also arguable), it is also used to make MFC appear more.. erm.. simplified.   ;Quote:Original post by plywood(1) All "controls" are really just interactive Windows, like the main Window of your application; just sub-classed and specialized to perform certain functions.They're not sub-classed. Just like you provide a window class definition and a window procedure for your windows, the OS provides window classes (with static identifiers like "EDIT", "BUTTON" or "ComboBoxEx32").Quote:(2a) Every control has a UINT "resource" identifier associated with it, so that when a WindProc receives a message that, say, a button has been pressed, it can identify which button control fired that event.This is wrong. Every control is identified by its HWND window handle. When the window procedure is invoked on a per window class basis, it is passed the handle to the specific window originating the message, the msg (UINT) and two dependent parameters for auxiliary information. In some cases, a parent window gets notified when a child window generates an event (in reality, the child window generates multiple events, but handles the bulk of them for itself, with only a few being passed upwards as notifications). Because the Win32 architecture did not allow for passing window handles in notifications, child windows that may generate notifications then need to be given numerical identifiers, which is where you got this misperception.Quote:(2b) These resource IDs are created magically from a mystical geiser located somewhere in Antarctica that spews them out about every half hour. The programmer needs only to capture these IDs as they are cast out into the open air, but never has to worry about how they are generated or otherwise made.This is completely wrong. Resource IDs are manually assigned; what you're not seeing is that people sometimes move the resource creation into a "resource script" (look for files with the .rc extension), which is compiled alongside the application. There's typically a resource header (unsurprisingly often called resource.h) that defines the resource IDs as numeric constants and is included by both the resource script and the application source code.See Resource Compiler for more information.Quote:(3) Making a "Hello, Dialogs!" dialog (not a system dialog or a MessageBox) pop up when the main WindProc receives, say, a WM_CREATE message is as easy as the following...The LPTSTR template parameter in CreateDialog is actually to specify a dialog template string - basically, an identifier corresponding to a resource for the dialog box, as in the section above. It lets you define your various dialog interfaces in a separate resource file, then create them by identifier in your application source.Quote:(4) Windows operate according to a hierarchy, much like Java has a container hierarchy of windows, frames, panels, etc. The Windows paradigm is as follows:Window > Dialog > Control.No. Everything in Windows is a window (HWND). That's the origin of the OS name.Quote:(5) The difference between a bona fide Windows message, such as WM_DESTROY, and a notification, such as BN_CLICKED, is that Windows Messages get handled in window procedures, and notifications are fed to hungry lions living at the bottom of the system freestore.Haha, funny. Not. Notifications are "bona fide" messages; they simply indicate that the origin of the message is from a control other than the window the procedure is being called for. For instance, when your main window (or dialog) gets a BN_CLICKED notification, it means that the window message actually comes from another window that you don't necessarily have access to by handle/procedure; you're just being given a chance to respond to that window's event.Quote:(6) There is no difference between a macro and a function.A macro is an anchor for textual substitution that occurs before the compiler starts compiling your source code. Generally, it effects a text expansion, though sometimes it replaces a meaningful textual identifier with a numeric literal. It's a feature of the C and C++ programming languages, which Win32 takes advantage of.   ;  plywood:Quote:The difference between a bona fide Windows message, such as WM_DESTROY, and a notification, such as BN_CLICKED, is that Windows Messages get handled in window procedures, and notifications are fed to hungry lions living at the bottom of the system freestore.Oluseyi:Quote:Haha, funny. Not. Notifications are "bona fide" messages; they simply indicate that the origin of the message is from a control other than the window the procedure is being called for...No, YOU'RE not funny! No pun intended.   ;Plywood, I have a question for you. One that's arguably more important than yours: Why the hell are you programming using Win32? Win32 is based on the older, Pascal-centric API. It's a godawful way to write Windows apps -- especially as there are far, far better tools available for Windows development. .NET is the preferred tool for Windows programming today. It had some teething troubles early on, but it's very mature now.The problems you're describing are literally non-issues if you use .NET. Unless you're a masochist, are being forced to use Win32 for weird compatibility reasons, or are just interested in software archeology, there really is no need to use Win32 any more.Use the best tool for the job. That way, you'll stay sane longer.   ;Quote:Original post by stimarcoPlywood, I have a question for you. One that's arguably more important than yours: Why the hell are you programming using Win32? Just curious, are there shiny new "Win32" APIs for C and C++? Or is all the new stuff for .Net languages (C#, VB.net etc.)?I'm kinda ignorant on this topic, so go slow :)   ;Quote:Original post by fpsgamerQuote:Original post by stimarcoPlywood, I have a question for you. One that's arguably more important than yours: Why the hell are you programming using Win32? Just curious, are there shiny new "Win32" APIs for C and C++? Or is all the new stuff for .Net languages (C#, VB.net etc.)?Well, It isn't exactly "shiny new" but the Microsoft Foundation Classes (MFC) are the alternative to using the raw Win32 API. These classes are written by Microsoft to aid programmers in developing windows applications using C++. Some people would argue that an understanding of Win32 before using MFC is important, and that is something in which I agree; however if you;re looking for something more current MFC would be your target.   