Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / desktop / Win32

My first Win32 UI

4.59/5 (8 votes)
3 Jan 2013CPOL3 min read 22.1K   8  
A sample application to present a simple dialog box using the Win32 API.

The Why

This article has come about during the work I'm doing to investigate audio generation technologies on the Windows platform, and it describes one core requirement I had, namely using the Win32 API to create and manage a Windows application UI.

There are many ways I could have gone about this, but for this work I wanted to get deep into the workings of the API, to understand techniques and develop my own resources, so I skipped the many UI libraries available, in favour of direct UI manipulation using the API.

There are many well documented examples out there, but none I seemed to meet my immediate need, which was for an application to open a simple form with a button and listbox, nothing else, something I could reuse and build on.

The How

Skipping the detailed explanations then, of which there are many available, and getting straight into the code, the first thing I wanted to do was design the presentation of the UI.

Using Visual Studio 2010 again, for the full version there is a built in editor for this, on the express version you will have to make use of an external tool such as Resedit, as described here. What these editors allow you to do is to create a form or window design, and generate what is know as a resource script from it. It is this resource script (a .rc file) whcih is then included in the main project to describe the form and manage access to the elements within it.

Without going into too much detail, for my sample, I created a simple dialog form for my application, with a single Button and a List Box, as below:

Image 1

From here, on saving the dialog, the tool creates two files, a .rc file, and another called resources.h. These need to be included in the main project.

The .rc file is the actual script describing the controls, for the form above this should look like:

C++
#include <windows.h>
#include <commctrl.h>
#include <richedit.h>
#include "resource.h"

//
// Dialog resources
//
LANGUAGE 0, SUBLANG_NEUTRAL
IDD_DIALOG1 DIALOG 0, 0, 277, 161
STYLE DS_3DLOOK | DS_CENTER | DS_MODALFRAME | DS_SHELLFONT | 
      WS_CAPTION | WS_VISIBLE | WS_POPUP | WS_SYSMENU
CAPTION "Sample Win32"
FONT 8, "Ms Shell Dlg"
{
    DEFPUSHBUTTON   "Show List", IDSHOWLIST, 22, 17, 46, 14
    LISTBOX         IDC_LIST1, 23, 47, 228, 96, WS_TABSTOP | WS_VSCROLL | 
                    LBS_NOINTEGRALHEIGHT | LBS_SORT | LBS_NOTIFY
}

On to the main part of the code. The entry point for the application is the WinMain function. Within this, the window defined above is created as a dialog box, as below:

C++
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
    LPSTR lpCmdLine, int nCmdShow)
{
    return DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), NULL, DlgProc);
}

Note in the DialogBox call, MAKEINTRESOURCE refers to the name of the resource created previously which is to be shown on the screen. Note also the reference to DlgProc. This is the function that handles the callback from the dialog window, that is the response from the user.

DlgProc handles the response, known as a message, received from the dialog, as below:

C++
BOOL CALLBACK DlgProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
{
    switch(Message)
    {
        case WM_INITDIALOG:
            // This is where we set up the dialog box, and initialise any default values

        break;
        case WM_COMMAND:
            switch(LOWORD(wParam))
            {
                case IDSHOWLIST:
                {
                    HWND hListBox = ::GetDlgItem(hwnd, IDC_LIST1);
                    for (int i = 0 ; i < 8 ; i++)
                    SendMessage( hListBox, LB_ADDSTRING, 0, (LPARAM)("Modes List Box"));
                }
                break;
            }
        break;
        case WM_CLOSE:
            EndDialog(hwnd, 0);
        break;
        default:
            return FALSE;
    }
    return TRUE;
}

Here, the code looks at the value of Message returned. If this is WM_COMMAND, it means that the user interacted with the window in some way. The actual control involved in that interaction can be derived by looking at the value of wParam, and will be one of the values defined in Resource.h. In this case, if the button was clicked, then WM_COMMAND will be set to the ID of the button, IDSHOWLIST, and code can be written to handle this message.

The simple example code here populates the list box with a number of lines of text data. To do this, a reference to the handle of the ListBox is found (note that all controls are actually seen as windows in their own right). Given this handle, messages can be sent to the ListBox, in this case to add text, indicated by the LB_ADDSTRING parameter. 

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)