Menu

Creating a template for dialog wrapper

2004-09-27
2012-09-26
  • Nobody/Anonymous

    Hi,

    the last days I tried to do a simple dialog wrapper class (inspired by some tutorials/articles) an as I am a newbie to this, I am happy that I got it work!
    (at least I got no more system errors!)

    Now I wanted to make this a template for new DEV-C++ projects.

    First:
    Can anyone check if this code is not too dangerous?

    Second:
    How can I make it a DEV-C++ template.

    Thank you
    Tom

    PS:
    Here is the source

    ===============

    WinMain.cpp

    // Include the stuff you need

    include "CBaseDlg.h"

    // Windows main function
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)

    {
    // First instance of the base dialog class
    CBaseDlg MainDlg;

    // Run the main dialog
    return MainDlg.RunDlg(MainDlg.CreateDlg(IDD_DLG));
    }

    ==================================================================================================

    CBaseDlg.h

    ifndef BASE_DLG_H

    define BASE_DLG_H

    define STRICT // For strict type checking

    include <windows.h> // Include windows stuff

    include "Resource.h"

    // Declaration of base dialog window class
    class CBaseDlg
    {
    public:

    CBaseDlg();             // Constructor
    virtual ~CBaseDlg();    // Destructor
    
    // Declare static dialog box procedure, it's a windows callback function and has to be static
    // This procedure will call the dialog objects member function
    static BOOL CALLBACK DlgProcStatic(HWND m_hWnd, unsigned int uiMessage, WPARAM wParam, LPARAM lParam);
    
    //  This function creates a modeless dialog from a resource
    HWND CreateDlg(unsigned int uiResID);
    
    //  This function runs the dialog
    WORD RunDlg(HWND hWnd);
    

    private:

    protected:
    // This is the member callback function for the dialog window
    virtual BOOL CALLBACK DlgProc(HWND m_hWnd, unsigned int uiMessage, WPARAM wParam, LPARAM lParam);

    };

    endif // BASE_DLG_H

    ==================================================================================================

    CBaseDlg.cpp

    include "CBaseDlg.h"

    include "AboutDlg.h"

    // Implementation of constructor
    CBaseDlg::CBaseDlg()
    {
    }

    // Implementation of destructor
    CBaseDlg::~CBaseDlg()
    {
    }

    // Create the dialog
    HWND CBaseDlg::CreateDlg(unsigned int uiResID)
    {
    HWND hWnd = NULL;
    // Create windows dialog (with a static dialog box procedure!)
    // and pass the dialog window its 'this' pointer as LPARAM
    // to get and check it when processing the WM_INITDIALOG message.
    // This can be done by using 'CreateDialogParam'.
    hWnd = CreateDialogParam( GetModuleHandle(NULL), // Instance of the application
    MAKEINTRESOURCE(uiResID), // Resource ID of dialog
    NULL, // Parent of dialog
    DlgProcStatic, // Static dialog procedure
    (LPARAM) this); // Additional parameter

    return hWnd;
    }

    // Run the dialog
    WORD CBaseDlg::RunDlg(HWND hWnd)
    {
    MSG msg;

    if (hWnd == NULL) // Check if dialog window is created, otherwise return
    {
    return false;
    }

    // The usual message loop
    while(GetMessage(&msg, NULL, 0, 0))
    {
    if ((IsWindow(hWnd) == false) || (IsDialogMessage(hWnd,&msg) == false))
    {
    // If window is not existing or the message is not intended for this dialog window
    // Dispatch message to the appropriate window
    TranslateMessage(&msg);
    DispatchMessage(&msg);
    }
    }

    return (msg.wParam);
    }

    // Static dialog procedure
    BOOL CALLBACK CBaseDlg::DlgProcStatic(HWND hWnd, unsigned int uiMessage, WPARAM wParam, LPARAM lParam)
    {
    CBaseDlg* pThis = NULL; // Make it NULL to check it later

    // This is the first message is received at dialog window creation
    if (uiMessage == WM_INITDIALOG) // If dialog window is created
    {
    // Get 'this' pointer information from LPARAM
    pThis = (CBaseDlg) lParam;
    // Associate it to the dialog window
    SetWindowLong(hWnd, GWL_USERDATA, (long) pThis);
    }
    else
    {
    // Get associated dialog window instance
    pThis = (CBaseDlg
    ) GetWindowLong(hWnd, GWL_USERDATA);
    }

    if (pThis == NULL) // If pThis is not yet set (WM_INITDIALOG not processed)
    {
    return false; // Return an wait for the WM_INITDIALOG message, where it is set
    }
    else
    {
    // Call the member function with its 'this' pointer
    return(pThis->DlgProc(hWnd, uiMessage, wParam, lParam));
    }
    }

    // Implementation of member function (dialog box procedure) called by the static one
    BOOL CALLBACK CBaseDlg::DlgProc(HWND hWnd, unsigned int uiMessage, WPARAM wParam, LPARAM lParam)
    {
    switch (uiMessage) // Handle messages
    {
    case WM_INITDIALOG: // Dialog is created
    return 0;

    case WM_COMMAND:    // Operate command
      switch (LOWORD(wParam))
      {
        case ID_BUTTON:
          // Open 'About Dialog'
          CAboutDlg AboutDlg;
          AboutDlg.RunDlg(AboutDlg.CreateDlg(IDD_ABOUT));
          break;
      }
      return 0;
    
    case WM_CLOSE:
      DestroyWindow(hWnd);
      return 0;
    
    case WM_DESTROY:    // Dialog window is destroyed
      PostQuitMessage(0);
      return 0;
    
    default:
      return 0;
    

    }
    }

    ==================================================================================================

    AboutDlg.h

    ifndef ABOUT_DLG_H

    define ABOUT_DLG_H

    include "CBaseDlg.h"

    class CAboutDlg : public CBaseDlg // Derive from dialog base class
    {
    public:
    CAboutDlg(); // Use default constructor of base class
    virtual ~CAboutDlg(); // Use default destructor of base class

    private:
    // This is the special member callback function for the 'About' dialog window
    virtual BOOL CALLBACK DlgProc(HWND m_hWnd, unsigned int uiMessage, WPARAM wParam, LPARAM lParam);

    protected:

    };

    endif // ABOUT_DLG_H

    ==================================================================================================

    AboutDlg.cpp

    include "AboutDlg.h"

    // Implementation of constructor
    CAboutDlg::CAboutDlg()
    {
    }

    // Implementation of destructor
    CAboutDlg::~CAboutDlg()
    {
    }

    // Implementation of member function (dialog box procedure) called by the static one
    BOOL CALLBACK CAboutDlg::DlgProc(HWND hWnd, unsigned int uiMessage, WPARAM wParam, LPARAM lParam)
    {
    switch (uiMessage) // Handle messages
    {
    case WM_INITDIALOG: // Dialog is created
    return 0;

    case WM_COMMAND:    // Operate command
      switch (LOWORD(wParam))
      {
        case ID_OK:
          DestroyWindow(hWnd);
          break;
      }
      return 0;
    
    case WM_CLOSE:
      DestroyWindow(hWnd);
      return 0;
    
    default:
      // Messages that are not handled are passed to the base dialog window procedure
      return CBaseDlg::DlgProc(hWnd, uiMessage, wParam, lParam);
    

    }
    }

     
    • Jim W.

      Jim W. - 2004-09-27

      First, what are you using for resource files ( .h and .rc )? (Also, you might want to make all the header guards consistent with the filenames....)

      Second, after you have a working Project, use File > New > Template. (In Dev-C++ 4.9.9.0. Don't remember when that feature first appeared, though....)

      -- Jim.

       
    • Nobody/Anonymous

      Hi,

      Thank you, it was pretty easy to create a template.

      These are the resource files:

      Resource.rc

      include <windows.h> // Include windows stuff

      include "Resource.h" // Include resource IDs

      // The main dialog window
      IDD_DLG DIALOG DISCARDABLE 0, 0, 140, 90
      STYLE DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE
      CAPTION "Dialog Wrapper Class Example"
      FONT 8, "MS Sans Serif"
      BEGIN
      PUSHBUTTON "Click me", ID_BUTTON, 50, 38, 40, 14
      END

      // This could be the about dialog
      IDD_ABOUT DIALOG DISCARDABLE 0, 0, 200, 100
      STYLE DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE
      CAPTION "Dialog"
      FONT 8, "MS Sans Serif"
      BEGIN
      PUSHBUTTON "&Ok", ID_OK, 80, 73, 40, 14
      LTEXT "By Thomas Henle", IDC_ABOUT_TEXT, 70, 20, 50, 8
      END
      ==========================================

      Resource.h

      // Define here the IDs for your resources

      define IDD_DLG 100

      define IDD_ABOUT 101

      define IDC_ABOUT_TEXT 1001

      define ID_BUTTON 40001

      define ID_OK 40002

      I'm not shure if this is the correct way to have an message loop for all instances. I'd rather use 'DialogBox' instead of 'CreateDialogParam', but then I got some problems with the 'this' pointer in the static callback function.

      Is there another way?

      Tom

       
    • Kip

      Kip - 2004-09-28

      // Global static dialog proc through which all CWinApp objects pass through...
      BOOL CALLBACK StaticDialogProcKernel(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
      {
      // Variables...
      HGLOBAL hMemory = 0;
      CWinApp *pMemory = NULL;
      CWinApp
      pDialogObject = NULL;

      // Dialog just being created...
      if(msg == WM_INITDIALOG)
      {
          // Get object location...
          pDialogObject = (CWinApp *) lParam;
      
              // Failed...
              if(!pDialogObject)
              {
                  // Tell user what's going on, then terminate...
                  MessageBox(hDlg, &quot;Dialog creation failed miserably...&quot;,
                             &quot;Error&quot;, MB_OK | MB_ICONERROR);
                  ExitProcess(1);
              }
      
          // Remember dialog handle...
          pDialogObject-&gt;hDialog = hDlg;
      
          // Bind object to dialog...
      
              // Allocate storage to hold address of object and lock it...
              hMemory = GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT, sizeof(pDialogObject));
              pMemory = (CWinApp **) GlobalLock(hMemory);
      
                  // Failed...
                  if(!pMemory)
                  {
                      // Kill it...
                      EndDialog(pDialogObject-&gt;GetHandle(), -1);
                      return FALSE;
                  }
      
              // Initialize, then unlock...
             *pMemory = pDialogObject;
              GlobalUnlock(hMemory);
      
              // Bind, and check for error...
              if(!SetProp(hDlg, CWINAPP_PROPERTY_ID, hMemory))
              {
                  // Kill it...
                  EndDialog(pDialogObject-&gt;GetHandle(), -1);
                  return FALSE;
              }
      }
      
      // Already bound, get object location...
      pDialogObject = (CWinApp *) CWinApp::GetObject(hDlg);
      
          // No object handle to address received, abort to avoid seg fault...
          if(!pDialogObject)
              return FALSE;
      
      // Pass window message to object's dialog procedure...
      return pDialogObject-&gt;DialogProc(hDlg, msg, wParam, lParam);
      

      }

      =)

      Kip

       
    • Nobody/Anonymous

      Hi,

      wow, that is a heavy piece of code for a beginner like me.
      I hope I can sleep with that! :-)

      You allocate memory to store the 'this' pointer.
      You lock the memory and so got a pointer to that allocated memory.
      You store the 'this' pointer to that memory.
      You unlock the memory.

      Now I found the 'SetProp' function in the API-Help but not the
      'CWINAPP_PROPERTY_ID' constant.

      So, to be honest, from that point I don't exactly know what's going on.

      Why is this better than using 'SetWindowLong/GetWindowLong'?

      Thank you very much!!

      Tom

       
    • Kip

      Kip - 2004-09-28

      SetWindowLong / GetWindowLong access the user data section of the class, which is possibly shared by other programs / classes. SetProp lets us setup our own special area. CWINAPP_PROPERTY_ID is just a string constant. Replace with the name of your class.

      Good luck =)

      Kip

       
    • Kip

      Kip - 2004-09-29

      No problem. Enjoy =)

      Kip

       
    • Nobody/Anonymous

      Could you create a SDI with toolbar template for us ?

       
    • Nobody/Anonymous

      What is SDI?

       
    • Nobody/Anonymous

      I tried this and it works fine!

      Once more, thank you!!!

       

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.