Menu

Creating a Tollbar

Eric Davis
2009-01-16
2012-09-26
  • Eric Davis

    Eric Davis - 2009-01-16

    I've been trying to create a toolbar but can't get the toolbar window to create. Does anybody know why it wont work?

    ////////////////////////////////////////////////////////////////////////////////////

    include <windows.h>

    include <commctrl.h>

    include "resource.h"

    / Declare Windows procedure /
    LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);
    / Make the class name into a global variable /
    char szClassName[ ] = "WindowsApp";
    HWND hwndToolBar;

    / This function is called by the Windows function DispatchMessage() /

    LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
    switch (message) / handle the messages /
    {
    case WM_CREATE:
    {
    //InitCommonControlsEx(ICC_BAR_CLASSES);
    /// I tried to use the above function, but the compiler can't find its // declaration

            TBADDBITMAP tbab; 
            TBBUTTON tbb[3];
    

    //////////// Here's the problem area ///////////

            hwndToolBar = CreateWindowEx(
            0, 
            TOOLBARCLASSNAME, 
            (LPSTR)NULL,
            WS_CHILD,
            0,
            0, 
            0, 
            0,
            hwnd, 
            (HMENU)IDTB_TOOLBAR, 
            (HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE),
            NULL);
    

    ///// The create window function is failing //////////////////

            if (!hwndToolBar)
            {
                MessageBox(NULL, &quot;Tool Bar Failed.&quot;, &quot;Error&quot;, MB_OK | MB_ICONERROR);
                return 0;
            }
    
            SendMessage(hwndToolBar, TB_BUTTONSTRUCTSIZE, (WPARAM)sizeof(TBBUTTON), 0);
    
            SendMessage(hwndToolBar, TB_SETBITMAPSIZE, (WPARAM)0, (LPARAM)MAKELONG(20, 20));
    
            tbab.hInst = (HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE); 
            tbab.nID   = IDB_TOOLBITMAP; 
            SendMessage(hwndToolBar, TB_ADDBITMAP, (WPARAM) 2, (LPARAM) &amp;tbab);
    
            ZeroMemory(tbb, sizeof(tbb));
    
            tbb[0].iBitmap = 20; 
            tbb[0].idCommand = TB_TEST1; 
            tbb[0].fsState = TBSTATE_ENABLED; 
            tbb[0].fsStyle = TBSTYLE_BUTTON;
    
            tbb[1].fsStyle = TBSTYLE_SEP;
    
            tbb[2].iBitmap = 21; 
            tbb[2].idCommand = TB_TEST2; 
            tbb[2].fsState = TBSTATE_ENABLED; 
            tbb[2].fsStyle = TBSTYLE_BUTTON;
    
            SendMessage(hwndToolBar, TB_ADDBUTTONS, 3, (LPARAM)&amp;tbb);
            ShowWindow(hwndToolBar, SW_SHOW); 
        }
        break;
    
        case WM_COMMAND: 
        {
            switch(LOWORD(wParam))
            {
                case TB_TEST1:
                {
                    MessageBox(NULL, &quot;Toolbar Button One&quot;, &quot;Success&quot;, MB_OK | MB_ICONINFORMATION);
                }
                break;
    
                case TB_TEST2:
                {
                    MessageBox(NULL, &quot;Toolbar Button Two&quot;, &quot;Success&quot;, MB_OK | MB_ICONINFORMATION);
                }
                break; 
            }
            return 0;
        } 
        break;
    
        case WM_DESTROY:
            PostQuitMessage (0);       /* send a WM_QUIT to the message queue */
            break;
        default:                      /* for messages that we don't deal with */
            return DefWindowProc (hwnd, message, wParam, lParam);
    }
    
    return 0;
    

    }

    int WINAPI WinMain (HINSTANCE hThisInstance,
    HINSTANCE hPrevInstance,
    LPSTR lpszArgument,
    int nFunsterStil)

    {
    HWND hwnd; / This is the handle for our window /
    MSG messages; / Here messages to the application are saved /
    WNDCLASSEX wincl; / Data structure for the windowclass /

    /* The Window structure */
    wincl.hInstance = hThisInstance;
    wincl.lpszClassName = szClassName;
    wincl.lpfnWndProc = WindowProcedure;      /* This function is called by windows */
    wincl.style = CS_DBLCLKS;                 /* Catch double-clicks */
    wincl.cbSize = sizeof (WNDCLASSEX);
    
    /* Use default icon and mouse-pointer */
    wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
    wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
    wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
    wincl.lpszMenuName = NULL;                 /* No menu */
    wincl.cbClsExtra = 0;                      /* No extra bytes after the window class */
    wincl.cbWndExtra = 0;                      /* structure or the window instance */
    /* Use Windows's default color as the background of the window */
    wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND;
    
    /* Register the window class, and if it fails quit the program */
    if (!RegisterClassEx (&amp;wincl))
        return 0;
    
    /* The class is registered, let's create the program*/
    hwnd = CreateWindowEx (
           0,                   /* Extended possibilites for variation */
           szClassName,         /* Classname */
           &quot;Windows App&quot;,       /* Title Text */
           WS_OVERLAPPEDWINDOW, /* default window */
           CW_USEDEFAULT,       /* Windows decides the position */
           CW_USEDEFAULT,       /* where the window ends up on the screen */
           544,                 /* The programs width */
           375,                 /* and height in pixels */
           HWND_DESKTOP,        /* The window is a child-window to desktop */
           NULL,                /* No menu */
           hThisInstance,       /* Program Instance handler */
           NULL                 /* No Window Creation data */
           );
    
    /* Make the window visible on the screen */
    ShowWindow (hwnd, nFunsterStil);
    
           //ShowWindow(test, SW_SHOW); 
    /* Run the message loop. It will run until GetMessage() returns 0 */
    while (GetMessage (&amp;messages, NULL, 0, 0))
    {
        /* Translate virtual-key messages into character messages */
        TranslateMessage(&amp;messages);
        /* Send message to WindowProcedure */
        DispatchMessage(&amp;messages);
    }
    
    /* The program return-value is 0 - The value that PostQuitMessage() gave */
    return messages.wParam;
    

    }

     
    • cpns

      cpns - 2009-01-18

      OK I no longer bother to install Dev-C++, so I downloaded the latest Win32API 3.13 from https://sourceforge.net/project/showfiles.php?group_id=2435&package_id=11550 (Dev-C++ uses a version of this, I doubt that the Dev-C++ installed version differs significantly with respect to this problem.

      InitCommonControlsEx is dependent upon the following pre-processor directive:

      if (_WIN32_IE >= 0x0300)

      I have no idea what MinGW sets this to by default is at all, but you might want to add a -D_WIN32_IE=0x0400 definition to the compiler options for the project. You could also run a test and simply printf("_WIN32_IE=0x%X", _WIN32_IE ) ; and see what it defaults to.

      Being relatively old, MinGW/GCC GCC 3.x probably sets this version macro lower than current Microsoft products.

      This is almost certainly your problem, although having installed the MS SDK, you may have screwed things up royally by now.

      Plain InitCommonControls() has no version dependency, so that suggestion would have worked, but it is rather defeatist.

      Remember header files are just plain text source files, you are free to look at them if you need to investigate problems such as this.

      Clifford

       
    • Eric Davis

      Eric Davis - 2009-01-18

      BTW: I updated the includes and lib's as you suggested.

       
    • cpns

      cpns - 2009-01-18

      > Well, that made the compiler swallow INITCOMMONCONTROLSEX and InitCommonControlsEx()
      Are you sure that you commenting them out was not in fact what really did it.

      > comctl32.dll seems to be the problem. Hmm...

      I doubt that. Why would you blame a library that is an integral part of the operating system, is used by almost every program running on your machine, and on every other Windows machine on the planet, rather than suspecting your own code!? Occam's Razor applies.

      How does it crash? What are the symptoms.

      Unfortunately your code cannot be tested without the resource scripts too.

      I suspect that it is crashing exactly because you commented out the initialisation!

      Clifford

       
    • Eric Davis

      Eric Davis - 2009-01-18

      ////////////////////////////////////////////////////////////////////
      case WM_CREATE:
      {
      // INITCOMMONCONTROLSEX icce;
      // icce.dwSize = sizeof(INITCOMMONCONTROLSEX);
      //icce.dwICC = ICC_BAR_CLASSES;

      // InitCommonControlsEx(&icce);

      ////////////////////////////////////////////////////////////////////

      I did that so you could try the program as it was originally written--without InitCommonControlsEx(). It's easy enough to edit out these "//" When I compile and run the program without InitCommonControlsEx() as part of the source code, it loads fine but doesn't create the toolbar.

      "I doubt that. Why would you blame a library that is an integral part of the operating system, is used by almost every program running on your machine, and on every other Windows machine on the planet, rather than suspecting your own code!? Occam's Razor applies. "

      The error window that pops up seems to point to module: comctl32.dll. My assertion is that the program and function in question are causing a conflict within that dll.

      "Unfortunately your code cannot be tested without the resource scripts too. "

      Why not? I've offered the three files that I used in this program: main.cpp, resource.h and resource.rc. The only file I didn't include was the bitmap for the toolbar, but any old scratch would probably work, providing you could get the toolbar to load up.

       
    • Eric Davis

      Eric Davis - 2009-01-19

      Now I'm having the same trouble while trying to create a status bar. It's related to the commctrl.h file since both require it. The structure is much the same as the toolbar source...

      /////////////////////////////////////////////////////////////////////////

      case WM_CREATE:
      {
      hWndStatusBar = CreateWindowEx(
      0,
      STATUSCLASSNAME,
      NULL,
      WS_CHILD | WS_VISIBLE | SBARS_SIZEGRIP,
      0,
      0,
      0,
      0,
      hWnd,
      (HMENU)IDC_STATUSBAR,
      (HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE),
      NULL);

              if (!hWndStatusBar)
              {
                  MessageBox(NULL, &quot;Failed To Create The Status Bar&quot;, &quot;Error&quot;, MB_OK | MB_ICONERROR);
                  return 0;
              }
      
       
    • cpns

      cpns - 2009-01-19

      > I did that so you could try the program as it was originally written
      > --without InitCommonControlsEx().

      We don't read minds. The interesting code is the code you are having a problem with, not the code that 'works'.

      > It's easy enough to edit out these "//"

      And just as easy for you to have done it before posting. I don't need the help, you do. Don't make me work (or expect me to read your mind).

      > My assertion is that the program and function in question
      > are causing a conflict within that dll.

      And I still doubt the validity of the assertion.

      > Why not? I've offered the three files that I used in this
      > program: main.cpp, resource.h and resource.rc.

      You have indeed. My mistake, my apologies.

      > The only file I didn't include was the bitmap for the toolbar,
      > but any old scratch would probably work,

      True perhaps, but that might require more work than I am prepared to put in. ;-)

      I believe your problem may be the hInstance parameter for CreateWindowEx(). You passed:

      (HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE)

      Googling for examples, I observe:

      GetModuleHandle(NULL)

      Try that. I have not tried it myself.

      Clifford

       
    • Eric Davis

      Eric Davis - 2009-01-19

      Same results. I added some error handling to see what would come up:

      if (!hwndToolBar)
      {
      LPVOID lpMsgBuf;

              FormatMessage( 
              FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
               NULL,
               GetLastError(),
               MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
               (LPTSTR) &amp;lpMsgBuf,
               0,
               NULL 
               );
      
               // Display the string.
             MessageBox( NULL, (LPSTR)lpMsgBuf, &quot;GetLastError&quot;, MB_OK|MB_ICONINFORMATION );
      
              // Free the buffer.
              LocalFree( lpMsgBuf );
      
              }
      
       
    • Eric Davis

      Eric Davis - 2009-01-20

      I just tried to run the same program through VC++ 2008 and had the very same problems as I had while using Dev-C++. I'm truly lost on this one. All of the examples are the same, yet I can't get it to work. Strange...

       
    • Eric Davis

      Eric Davis - 2009-01-20

      Welp... I found an example that works. I haven't figured out why it works and the other didn't, but it compiled and ran right through VC++. I'm gonna give it a run through Dev-C++ tomorrow. Phew! That was a long journey.

       
    • cpns

      cpns - 2009-01-20

      > I'm gonna give it a run through Dev-C++ tomorrow. Phew!

      Why bother if it works in VC++? What I would do, is build your original code in VC++ and use its far superior debugger to determine exactly where it is crashing and why.

      Clifford

       
    • Eric Davis

      Eric Davis - 2009-01-16

      "TOOLBARCLASSNAME" seems be the problem, but I don't know how to fix it.

      ////////////////////////////////////////////////////////////////////////

      hwndToolBar = CreateWindowEx(
      0,
      TOOLBARCLASSNAME, //<-- the problem is with this class
      (LPSTR)NULL,
      WS_CHILD,
      0,
      0,
      0,
      0,
      hwnd,
      (HMENU)IDTB_TOOLBAR,
      (HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE),
      NULL);

       
    • Musa

      Musa - 2009-01-16

      check http://msdn.microsoft.com/en-us/library/bb775507(VS.85).aspx for InitCommonControlsEx as you used it incorrectly

       
    • Eric Davis

      Eric Davis - 2009-01-16

      20 C:\Documents and Settings\Eric\My Documents\programs\test11\main.cpp `INITCOMMONCONTROLSEX' undeclared (first use this function)

      The compiler isn't finding the declaration for the structure or the function.

      //////////////////////////////////////////////////////////////////////////////

                INITCOMMONCONTROLSEX icce;
                icce.dwSize = sizeof(INITCOMMONCONTROLSEX);
                icce.dwICC = ICC_BAR_CLASSES;
      
               InitCommonControlsEx(@icce);
      

      /////////////////////////////////////////////////////////////////////////////

      I also tried the CreateToolbarEx(), but that caused an error in the comctrl.dll.

      ////////////////////////////////////////////////////////////////////////////

      TBBUTTON tbb[3];

      hwndToolBar = CreateToolbarEx(
      
      hwnd,   
      WS_CHILD,   
      IDTB_TOOLBAR,   
      1,  
      hThisInstance,  
      IDB_TOOLBITMAP,     
      tbb,    
      3,  
      25,     
      25,     
      25,     
      25,     
      sizeof(TBBUTTON)
      

      );
      if (!hwndToolBar)
      {
      MessageBox(NULL, "Tool Bar Failed.", "Error", MB_OK | MB_ICONERROR);
      // return 0;
      }

       
    • Eric Davis

      Eric Davis - 2009-01-16

      I downloaded MS SDK and tried using their include files, but the results are the same.

       
    • anonymous nobody

      Change where you save to. Dev-C++ can throw strange errors if you save projects to a directory with spaces, or within the Dev-Cpp folder. Save somewhere like where I save (C:\mycstuff).

      -J.M

       
    • anonymous nobody

      Also, why did you declare WindowProcedure's prototype at the start of the program, but then proceed to declare the function itself before using the function??

      -J.M

       
    • Musa

      Musa - 2009-01-17

      If you can't get to use InitCommonControlsEx then just use InitCommonControls() or try to update you library.

       
    • Eric Davis

      Eric Davis - 2009-01-17

      "Also, why did you declare WindowProcedure's prototype at the start of the program, but then proceed to declare the function itself before using the function??"

      -J.M

      Prototyping is a habit, and I'm still learning.

      ///////////////////////////////////////////////////////////////////////////////

      "If you can't get to use InitCommonControlsEx then just use InitCommonControls() or try to update you library. "

      I tried to use the InitCommonControls() function, but it makes the program crash and is causing an error within the comctl32.dll. I've tried the library file that came with the ms sdk, but the results are the same.

      I should probably give up, but it seems important, and I really want to understand why it's not working.

       
    • cpns

      cpns - 2009-01-18

      Attempting to use the MS SDK was a really bad idea. I am surprised that it worked at all. In fact I doubt that it worked, and and suspect that the compiler is still using the original headers.

      You cannot use the MS SDK for technical and licensing reasons.

      You might update the Win32API from www.mingw.org

      You might just look in the header file <commctrl.h> to see if and how InitCommonControlsEx is defined and whether it is conditional upon some version macro for example.

      You might just use Microsoft's free tools and save yourself a lot of trouble.

      You might post tge full compile log as asked in the "PLEASE READ BEFORE POSTING A QUESTION" thread.

      You should stop putting your projects in "C:\Documents and Settings\Eric\My Documents\&quot; ans also mentioned in the above mentioned thread.

      Clifford

       
    • Eric Davis

      Eric Davis - 2009-01-18

      "you might want to add a -D_WIN32_IE=0x0400 definition to the compiler options for the project."

      Thank you...

      Well, that made the compiler swallow INITCOMMONCONTROLSEX and InitCommonControlsEx(), but the program is still crashing. comctl32.dll seems to be the problem. Hmm...

       
    • Eric Davis

      Eric Davis - 2009-01-18

      If anybody wants to try this out, here's the source...

      /////////////////////////////// resource.h //////////////////////////////////////////

      define IDTB_TOOLBAR 1000

      define IDB_TOOLBITMAP 1001

      define TB_TEST1 1002

      define TB_TEST2 1003

      /////////////////////////////////resource.rc/////////////////////////////////////////

      include "resource.h"

      IDB_TOOLBITMAP BITMAP "toolbar.bmp"

      ///////////////////////////////// main.cpp//////////////////////////////////////////

      include <windows.h>

      include <commctrl.h>

      include "resource.h"

      / Make the class name into a global variable /
      char szClassName[ ] = "WindowsApp";
      HWND hwndToolBar;

      / This function is called by the Windows function DispatchMessage() /

      LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
      {
      switch (message) / handle the messages /
      {
      case WM_CREATE:
      {
      // INITCOMMONCONTROLSEX icce;
      // icce.dwSize = sizeof(INITCOMMONCONTROLSEX);
      //icce.dwICC = ICC_BAR_CLASSES;

             // InitCommonControlsEx(&amp;icce);
      
              TBADDBITMAP tbab; 
              TBBUTTON tbb[3];
      
              hwndToolBar = CreateWindowEx(
              0, 
              TOOLBARCLASSNAME, 
              (LPSTR)NULL,
              WS_CHILD,
              0,
              0, 
              0, 
              0,
              hwnd, 
              (HMENU)IDTB_TOOLBAR, 
              (HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE),
              NULL);
      
              if (!hwndToolBar)
              {
                  MessageBox(NULL, &quot;Tool Bar Failed.&quot;, &quot;Error&quot;, MB_OK | MB_ICONERROR);
                  return 0;
              }
      
              SendMessage(hwndToolBar, TB_BUTTONSTRUCTSIZE, (WPARAM)sizeof(TBBUTTON), 0);
      
              SendMessage(hwndToolBar, TB_SETBITMAPSIZE, (WPARAM)0, (LPARAM)MAKELONG(20, 20));
      
              tbab.hInst = (HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE); 
              tbab.nID   = IDB_TOOLBITMAP; 
              SendMessage(hwndToolBar, TB_ADDBITMAP, (WPARAM) 2, (LPARAM) &amp;tbab);
      
              ZeroMemory(tbb, sizeof(tbb));
      
              tbb[0].iBitmap = 20; 
              tbb[0].idCommand = TB_TEST1; 
              tbb[0].fsState = TBSTATE_ENABLED; 
              tbb[0].fsStyle = TBSTYLE_BUTTON;
      
              tbb[1].fsStyle = TBSTYLE_SEP;
      
              tbb[2].iBitmap = 21; 
              tbb[2].idCommand = TB_TEST2; 
              tbb[2].fsState = TBSTATE_ENABLED; 
              tbb[2].fsStyle = TBSTYLE_BUTTON;
      
              SendMessage(hwndToolBar, TB_ADDBUTTONS, 3, (LPARAM)&amp;tbb);
              ShowWindow(hwndToolBar, SW_SHOW); 
          }
          break;
      
          case WM_COMMAND: 
          {
              switch(LOWORD(wParam))
              {
                  case TB_TEST1:
                  {
                      MessageBox(NULL, &quot;Toolbar Button One&quot;, &quot;Success&quot;, MB_OK | MB_ICONINFORMATION);
                  }
                  break;
      
                  case TB_TEST2:
                  {
                      MessageBox(NULL, &quot;Toolbar Button Two&quot;, &quot;Success&quot;, MB_OK | MB_ICONINFORMATION);
                  }
                  break; 
              }
              return 0;
          } 
          break;
      
          case WM_DESTROY:
              PostQuitMessage (0);       /* send a WM_QUIT to the message queue */
              break;
          default:                      /* for messages that we don't deal with */
              return DefWindowProc (hwnd, message, wParam, lParam);
      }
      
      return 0;
      

      }

      int WINAPI WinMain (HINSTANCE hThisInstance,
      HINSTANCE hPrevInstance,
      LPSTR lpszArgument,
      int nFunsterStil)

      {
      HWND hwnd; / This is the handle for our window /
      MSG messages; / Here messages to the application are saved /
      WNDCLASSEX wincl; / Data structure for the windowclass /

      /* The Window structure */
      wincl.hInstance = hThisInstance;
      wincl.lpszClassName = szClassName;
      wincl.lpfnWndProc = WindowProcedure;      /* This function is called by windows */
      wincl.style = CS_DBLCLKS;                 /* Catch double-clicks */
      wincl.cbSize = sizeof (WNDCLASSEX);
      
      /* Use default icon and mouse-pointer */
      wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
      wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
      wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
      wincl.lpszMenuName = NULL;                 /* No menu */
      wincl.cbClsExtra = 0;                      /* No extra bytes after the window class */
      wincl.cbWndExtra = 0;                      /* structure or the window instance */
      /* Use Windows's default color as the background of the window */
      wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND;
      
      /* Register the window class, and if it fails quit the program */
      if (!RegisterClassEx (&amp;wincl))
          return 0;
      
      /* The class is registered, let's create the program*/
      hwnd = CreateWindowEx (
             0,                   /* Extended possibilites for variation */
             szClassName,         /* Classname */
             &quot;Windows App&quot;,       /* Title Text */
             WS_OVERLAPPEDWINDOW, /* default window */
             CW_USEDEFAULT,       /* Windows decides the position */
             CW_USEDEFAULT,       /* where the window ends up on the screen */
             544,                 /* The programs width */
             375,                 /* and height in pixels */
             HWND_DESKTOP,        /* The window is a child-window to desktop */
             NULL,                /* No menu */
             hThisInstance,       /* Program Instance handler */
             NULL                 /* No Window Creation data */
             );
      
      /* Make the window visible on the screen */
      ShowWindow (hwnd, nFunsterStil);
      
      /* Run the message loop. It will run until GetMessage() returns 0 */
      while (GetMessage (&amp;messages, NULL, 0, 0))
      {
          /* Translate virtual-key messages into character messages */
          TranslateMessage(&amp;messages);
          /* Send message to WindowProcedure */
          DispatchMessage(&amp;messages);
      }
      
      /* The program return-value is 0 - The value that PostQuitMessage() gave */
      return messages.wParam;
      

      }

       

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.