Thread: SendMessage(add txt 2 listbox) won't work in WM_COMMAND

  1. #1
    Registered User
    Join Date
    Dec 2006
    Posts
    19

    Unhappy SendMessage(add txt 2 listbox) won't work in WM_COMMAND

    When I call SendMessage(hListBox, LB_ADDSTRING, (WPARAM) 0, (LPARAM) "LOL fclose!"); inside of case WM_COMMAND: it doesn't add anything to the listbox.

    When I call SendMessage(hListBox, LB_ADDSTRING, (WPARAM) 0, (LPARAM) "LOL fclose!"); inside of case WM_CREATE: it works just fine.

    This is my first C program, and so far it's going pretty well. However not fully understanding what I'm doing has come back to bite me.

  2. #2
    Registered User
    Join Date
    Mar 2005
    Location
    Mountaintop, Pa
    Posts
    1,058
    change
    Code:
    HWND hListBox;
    to
    Code:
     static  HWND hListBox;

  3. #3
    Registered User
    Join Date
    Dec 2006
    Posts
    19
    Thanks, it works now

  4. #4
    Registered User
    Join Date
    Dec 2006
    Posts
    19
    This may be asking for a bit much, but could anyone explain to me why static is necessary?

  5. #5
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    If it is not static, the value will be lost whenever the function leaves. So in WM_CREATE, where you freshly assigned it, it's still available. Then WndProc returns, the variable goes out of scope, and soon some other function call overwrites the memory. When WndProc is called for WM_COMMAND, the variable has an effectively random value.
    If it is static, it's preserved across function calls.

    Static, as popular as it is (including Petzold's Programming Windows), can be problematic, though. If you create more than one window of the class, this will fail spectacularly. (Since it's your main window, creating more than one is not very common, but not unheard of either: window-per-document programs such as recent Word versions or Acrobat Reader do it.) We're talking about such weird errors as "I do something in one window, but it's the other one that changes."
    Static variables in the WndProc are shared by all windows of that class. The second window would overwrite the variable containing the HWND of the first window's child with that of its own child.

    The universally correct solution is to create a WindowData struct and add sizeof(WindowData*) bytes to the window-specific bytes, then access that.
    Something like this (C++-style syntax, API names from memory):
    Code:
    const LPCTSTR CLASSNAME = TEXT("MyAppMainWindowClass");
    const size_t OFF_WNDDATA = 0; // Would be adjusted if you stored more stuff in the window extra bytes.
    
    LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
    
    struct MainWindowData
    {
      HWND hListBox;
      HWND hStaticBox;
      HWND hEditBox;
      HWND hButton1;
      HWND hButton2;
      HWND hButton3;
      HWND hButton4;
      // ...
    };
    
    LRESULT InitWindow(HWND me, MainWindowData *mydata);
    
    void RegisterClass()
    {
      WNDCLASSEX wcex;
      wcex.cbSize = sizeof(WNDCLASSEX);
      wcex.pfnWndProc = WndProc;
      wcex.lpszClassName = CLASSNAME;
      // ...
      wcex.cbWndExtra = sizeof(MainWindowData*);
    
      RegisterClassEx(&wcex);
    }
    
    MainWindowData *GetMainWindowData(HWND hwnd)
    {
      return reinterpret_cast<MainWindowData*>(
        GetWindowLongPtr(hwnd, OFF_WNDDATA));
    }
    
    LRESULT CALLBACK WndProc(HWND me, UINT msg, WPARAM w, LPARAM l)
    {
      MainWindowData *mydata = GetMainWindowData(me);
      switch(msg)
      {
      case WM_NCCREATE:
        // The very first message ever sent, so it's the best place to allocate the data.
        mydata = new MainWindowData;
        SetWindowLongPtr(me, OFF_WNDDATA, reinterpret_cast<LONG_PTR>(mydata));
        return 0; // Or 1, can't remember what indicates success.
    
      case WM_CREATE:
        return InitWindow(me, mydata);
      }
    
      // The last important part is to free the data again, else you'd get a memory leak if during the
      // lifetime of your program you open and close main windows every now and then.
      // WM_NCDESTROY is the very last message ever sent to a window.
      case WM_NCDESTROY:
        delete mydata;
        return 0;
      }
      return DefWindowProc(me, msg, w, l);
    }
    
    LRESULT InitWindow(HWND me, MainWindowData *mydata)
    {
      mydata->hListBox = CreateWindow("LISTBOX", NULL, WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_BORDER,
        0, 0, 500, 300, hwnd, (HMENU) 500, hInstance, NULL);
      // ...
    
      return 0;
    }
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  6. #6
    Registered User
    Join Date
    Mar 2005
    Location
    Mountaintop, Pa
    Posts
    1,058
    I just can't think of a single example in a Single Document Interface (SDI) situation
    where a parent and child window(s) is/are created with one window class. The child
    window(s) will only display the exact same functionality as the parent window, not to
    mention the questionable integrity of the variables if you don't use the additional coding
    mentioned above. Why would you want to display two windows with the exact functionality
    when one window will do? Also, the functionality that you get in the child window(s) may not
    be what you expect. For instance, I wrote a small parent/child test app with one window class.
    The parent has a button to create the child window. Depressing the button in the parent creates
    a child window with a button to create a child window. Depressing the button in the child window
    does not create another child window contrary to what the button indicates. To make the
    child button work requires some additional convoluted code in the window procedure to "unravel"
    the logic to have the parent window create the child window or somehow create another procedure for
    the child window. I ended up with a lot of "code bloat" to make this very basic app work reasonably
    decent. Maybe there is some demented developer out there working on the next "killer app" using this
    functionality. But IMHO, it serves no useful purpose. Thus, I don't think you'll run into problems
    with static unless you're that demented developer.

    The flip side being Multiple Document Interface (MDI) as found in MS Word can use one
    (or more) windows classes for it's child windows. The classes are used primarily
    to create different types of child windows. For instance, one class would be for child
    windows that would only display text, another class for child windows to only display
    graphics etc.

    So, it's either SDI with separate windows classes for parent and child or MDI

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Deal or No Deal listbox prob
    By kryptkat in forum Windows Programming
    Replies: 5
    Last Post: 03-30-2009, 06:53 PM
  2. Listbox stealing focus
    By Calthun in forum Windows Programming
    Replies: 3
    Last Post: 09-12-2004, 04:36 PM
  3. The Bludstayne Open Works License
    By frenchfry164 in forum A Brief History of Cprogramming.com
    Replies: 8
    Last Post: 11-26-2003, 11:05 AM
  4. fopen();
    By GanglyLamb in forum C Programming
    Replies: 8
    Last Post: 11-03-2002, 12:39 PM
  5. Getting FULL filename from listbox
    By Garfield in forum Windows Programming
    Replies: 8
    Last Post: 01-27-2002, 08:28 AM