Search This Blog

Monday, 16 April 2012

A dialog based Win32 C++ Application

1. Introduction


In this article, I’ll guide you how to write C++ (pure, means no MFC, no ATL, no WTL, no CLR and no .Net) Win32 application (with the help of images). When writing pure Win32 programs, usually you see tutorials on internet or in help files shows how to use “RAW” windows, by filling a WNDCLASSEX structure, calling RegisterClassEx and then CreateWindowEx. This is explained in detail in Charles Petzold's classic Programming Windows book – a must-have for any Win32 programmer.
But sometimes you don’t need to create a new window entirely from scratch, a simple dialog box would fill your needs.

In this article, I’ll discuss how to use a Dialog Box as the main window for your program or application, from scratch. A dialog box resource can be quickly created – with labels, editboxes, and buttons with no controls adjusting (which take lots of work and time) – using any resource editor. Here I’ll use Visual Studio 2010, but the steps should be similar for other Visual Studio versions, or even other IDEs, just learn basic concept.

I’ll use pure Win32 C++ code to keep things as simple as possible: no MFC, no ATL, no WTL, or whatever. There is also the use of TCHAR functions (declared in tchar.h, more information click here) to make the code portable with ANSI and Unicode, and only functions that are both x86 and x64 compatible.

1.1. Program structure

Our program will be composed of three files:
  • .cpp (source file) – the source code we’ll effectively write, and the central theme of this article.
  • .rc (resource script) – describes the dialog box resources, easily created by Visual Studio or any resource editor, or even by hand, and compiled with a resource compiler.
  • .h (resource header) – simply the macro constants used in the RC file to identify the resources, usually created automatically together with the RC script.

2. Let's Start

Before writing the C++ source code, open up the Visual Studio 2010 and we’ll create an Win32 project.

Goto the File >> New >> Project...


Select Win32 in Visual C++ Templates then Win32 Project and Enter you application name and press OK


Click on Next >


 Select Application Type as Windows application and click on Finish.

When doing so, following files will be created:
In "Header Files" folder.
  • CppWin32Dialog.h - Main header file of Application.
  • Resource.h - Header file for identifying our resources like images, sound files, text files, strings etc.
  • stdafx.h -  another header file of Application. Include file for standard system include files, or  project specific include files that are used frequently, but are changed infrequently
  • targetver.h - Including SDKDDKVer.h defines the highest available Windows platform. 
In "Resource Files" folder - It contains our resource files.
  • CppWin32Dialog.ico - Our main Application Icon.
  • small.ico - Our main Application TaskBar Icon.
  • CppWin32Dialog.rc - Application's resource script file.
In "Source Files" folder.
  • CppWin32Dialog.cpp - Application's main source code file.
  • stdafx.cpp - Source file that includes just the standard includes.

After all above it look similar to above image. (Click on image to Enlarge)


Now, we will remove unwanted materials to make application smaller in size, to do this :
Goto Resource View and delete Accelerator, Menu.

Creating Dialog as main window from resource editor.


Goto Resource View and right click on CppWin32Dialog.rc and click on Add resource.


Select "Dialog" and click "NEW".
In Properties Tab Set following properties of newly created dialog:
Caption = Main Window
Minimize Box = True
Style = Overlapped
Application Window = True
Visible = True
ID = frmMain
Center = True

Your Dialog is ready to use....

3. The source code

Now we have to customize the existing code.

Our C++ source will have only two functions:
  • WinMain – the program entry point, which will have the main program loop.
  • DialogProc – the dialog box procedure, which will process the dialog messages.

Let’s start writing and customizing the code :

First we have to delete all codes of "CppWin32Dialog.cpp" and paste the codes I have described below.
#include "stdafx.h"
#include "CppWin32Dialog.h"
#include "CommCtrl.h"
Above two lines tells compiler that to include "stdafx.h" and "CppWin32Dialog.h".

// For nice controls look 
#pragma comment(linker, \
  "\"/manifestdependency:type='Win32' "\
  "name='Microsoft.Windows.Common-Controls' "\
  "version='6.0.0.0' "\
  "processorArchitecture='*' "\
  "publicKeyToken='6595b64144ccf1df' "\
  "language='*'\"")

#pragma comment(lib, "ComCtl32.lib")

Above codes includes to give richer control look.

INT_PTR CALLBACK DialogProc(HWND ,UINT ,WPARAM ,LPARAM);

The above code predefine "DialogProc" function.

Writing WinMain Function.

int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine,  int nCmdShow)
{
 HWND hDlg;
 MSG msg;
 BOOL ret;
 InitCommonControls();
    hDlg = CreateDialogParam(hInstance, MAKEINTRESOURCE(frmMain), 0, DialogProc, 0);
    ShowWindow(hDlg, nCmdShow);

 // Main message loop:
 while((ret = GetMessage(&msg, 0, 0, 0)) != 0) 
 {
    if(ret == -1)
      return -1;

    if(!IsDialogMessage(hDlg, &msg)) 
 {
      TranslateMessage(&msg);
      DispatchMessage(&msg);
    }
  }

 return (int) msg.wParam;
}

This is our main function which include two function:
  • InitCommonControls() function - which initiate Common Controls to make control looks richer.
  • CreateDialogParam() function - which is used to create window or dialog form resource. (frmMain is Dialog ID)
It also include main message processing loop.

Writing DialogProc Function.

INT_PTR CALLBACK DialogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
 int wmId, wmEvent;
 PAINTSTRUCT ps;
 HDC hdc;
 UNREFERENCED_PARAMETER(lParam);
 switch (message)
 {
 case WM_INITDIALOG:
  return (INT_PTR)TRUE;

 case WM_COMMAND:
  wmId    = LOWORD(wParam);
  wmEvent = HIWORD(wParam);
  // Parse the menu selections:
  switch (wmId)
  {
                  case IDOK:
   PostQuitMessage(0);
   break;
  }
  break;
   case WM_PAINT:
  hdc = BeginPaint(hDlg, &ps);
  // TODO: Add any drawing code here...
  EndPaint(hDlg, &ps);
  break;
 case WM_DESTROY:
  PostQuitMessage(0);
  break;
 case WM_CLOSE:
  PostQuitMessage(0);
 break;

 }
 return (INT_PTR)FALSE;
}

This is our main dialog box procedure, which will process the dialog messages.

4 The final program

So here is our final program. It’s the C++ source code for a minimally functional Win32 dialog based program, with the message loop and visual styles properly enabled, just ready to go. You can keep this to use as the skeleton for any Win32 dialog based program.

// CppWin32Dialog.cpp : Defines the entry point for the application.
//

#include "stdafx.h"
#include "CppWin32Dialog.h"
#include <CommCtrl.h>
// For nice controls look 
#pragma comment(linker, \
  "\"/manifestdependency:type='Win32' "\
  "name='Microsoft.Windows.Common-Controls' "\
  "version='6.0.0.0' "\
  "processorArchitecture='*' "\
  "publicKeyToken='6595b64144ccf1df' "\
  "language='*'\"")

#pragma comment(lib, "ComCtl32.lib")

INT_PTR CALLBACK DialogProc(HWND ,UINT ,WPARAM ,LPARAM);

int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine,  int nCmdShow)
{
 HWND hDlg;
 MSG msg;
 BOOL ret;
 InitCommonControls();
    hDlg = CreateDialogParam(hInstance, MAKEINTRESOURCE(frmMain), 0, DialogProc, 0);
    ShowWindow(hDlg, nCmdShow);

 // Main message loop:
 while((ret = GetMessage(&msg, 0, 0, 0)) != 0) 
 {
    if(ret == -1)
      return -1;

    if(!IsDialogMessage(hDlg, &msg)) 
 {
      TranslateMessage(&msg);
      DispatchMessage(&msg);
    }
  }

 return (int) msg.wParam;
}

INT_PTR CALLBACK DialogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
 int wmId, wmEvent;
 PAINTSTRUCT ps;
 HDC hdc;
 UNREFERENCED_PARAMETER(lParam);
 switch (message)
 {
 case WM_INITDIALOG:
  return (INT_PTR)TRUE;

 case WM_COMMAND:
  wmId    = LOWORD(wParam);
  wmEvent = HIWORD(wParam);
  // Parse the menu selections:
  switch (wmId)
  {
    case IDOK:
   PostQuitMessage(0);
   break;
  }
  break;
   case WM_PAINT:
  hdc = BeginPaint(hDlg, &ps);
  // TODO: Add any drawing code here...
  EndPaint(hDlg, &ps);
  break;
 case WM_DESTROY:
  PostQuitMessage(0);
  break;
 case WM_CLOSE:
  PostQuitMessage(0);
 break;

 }
 return (INT_PTR)FALSE;
}

Final Touch

As our project using common controls for nice look and its .dll or library may not present  every computer. So we can include it to our executable through these settings....
 In Solution Explorer right click on "CppWin32Dialog" and goto properties as above image


 See and set Configuration : Active(Debug).
Goto "Configuration Properties" then "C/C++" then "Code Generation" then "Runtime Library".
and Change Multi-threaded Dll (/MDd) into Multi-threaded (/MTd).

Now 
See and set Configuration : Release.
Goto "Configuration Properties" then "C/C++" then "Code Generation" then "Runtime Library".
and  Change Multi-threaded Dll (/MD) into Multi-threaded (/MT).
finaly  click on "OK". and you are done.
This will include all .dll or library that are necessary.

Project Files:-
CppWin32Dialog.zip

License

This article, along with any associated source code and files, is licensed under A Public Domain dedication.

1 comment:

  1. Lifesaver tutorial!!!!
    Thank you so much!!! :D

    ReplyDelete

Popular Posts

Site Map