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));
}
// 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);
// 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;
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);
// 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;
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
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
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
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
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
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
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:
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;
}
}
==================================================================================================
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;
}
}
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.
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
// 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;
}
=)
Kip
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
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
No problem. Enjoy =)
Kip
Could you create a SDI with toolbar template for us ?
What is SDI?
I tried this and it works fine!
Once more, thank you!!!