Click here to Skip to main content
15,881,882 members
Articles / Desktop Programming / MFC
Article

Using Dialog Templates to create an InputBox() in C++

Rate me:
Please Sign up or sign in to vote.
4.79/5 (32 votes)
15 Mar 20066 min read 177.5K   4.5K   43   27
Using dialog templates to create an InputBox() in C++, similar to that of VB's InputBox().

Image 1

(Single line input box)

Image 2

(Multi-line input box)

Introduction

One day, I was writing a small Windows tool, and wanted to get some input from the user. Since my application was not an MFC, nor a console application, to my knowledge, there was no simple way to get the input from the user. The Windows API does a pretty job by giving us the MessageBox() function but nothing like the InputBox function. Since I wanted to keep my application slim and self-contained, I decided to investigate on how to use dialogs without using resources and without introducing too much of code.

Thus the Win32InputBox library was born.

In this article, I will illustrate how to create and use dialog boxes without creating dialog resources or using MFC. We will then use this technique to create an InputBox() function that is similar to VB's InputBox().

Background

It is important for the reader to be familiar with Windows messaging, and the window/dialog procedure mechanism. Nonetheless, I will be giving a simple introduction for beginners.

Introduction to dialog boxes - the classical way

Currently, to create a dialog box driven application, you have many choices. I'll list the most popular methods:

  1. MFC dialog based application (can be generated by the wizard).
  2. Plain Win32 API - using the IDE's dialog designer.
  3. Plain Win32 API - without using the dialog designer, instead, using the code to create all the controls and the dialog window.

Each of the mentioned methods above have their pros and cons, but that's beyond the scope of this article. Now as promised, here's a small overview on how each of the mechanisms work.

We start with the Plain Win32 API (using the dialog designer):

  1. The design part:
    • We start by designing our dialog with the editor.
    • We create controls (buttons, textboxes, ...).
    • We assign IDs to the controls.
  2. The coding part:
    • We write our WindowProc(), which will handle all the events related to our dialog.
    • We call the appropriate dialog creation method (CreateDialog() family, or DialogBox() function family).

If you are not using the dialog designer, you will have to create the controls in the code by calling the CreateWindow() function.

As for MFC dialog based applications, the concept is similar, however everything is wrapped into neat classes. So, all you have to do is:

  1. Design the dialog using the editor.
  2. Subclass CDialog, say as CMyDialog.
  3. Bind your subclassed class to the desired dialog ID.
  4. Overwrite the needed CDialog's methods to handle messages and events.

Introduction to dialog templates

What is a dialog template? It is a structure that defines the styles and dimensions of a given dialog. A dialog template is defined through the DLGTEMPLATE structure found in the Windows headers. There is an extended version of this structure that renders the latter obsolete. The DLGTEMPLATEEX is not defined anywhere in the header files, but is described in the MSDN. The extended dialog template (DLGTEMPLATEEX) is newer, and introduces more features.

A dialog template alone is enough to describe the dialog, but not the dialog items, thus the DLGITEMTEMPLATE/EX structures. These DLGITEMTEMPLATE[EX] structures will define the items inside the dialog.

When you use the dialog editor (in VC++'s IDE), you are visually constructing the dialog templates and the dialog item templates (however, in source code form). When you compile your application, the resources get compiled separately using the RC.EXE (resource compiler) tool, which will produce the .RES (binary file) out of the .RC (text file), and finally everything will be linked together to produce one executable module.

Here's how DLGTEMPLATE and DLGITEMTEMPLATE are described in a .RC file:

IDD_INPUTBOX DIALOGEX 22, 17, 231, 109
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | 
                                    WS_CAPTION | WS_SYSMENU
CAPTION "Win32InputBox"
FONT 8, "MS Shell Dlg", 700, 0, 0x0
BEGIN
    LTEXT           "Prompt:",IDC_INPUTBOX_PROMPT,6,4,157,
                                             33,SS_NOPREFIX
    EDITTEXT        IDC_INPUTBOX_DLG_EDIT1,6,37,216,14,
                                             ES_AUTOHSCROLL
    EDITTEXT        IDC_INPUTBOX_DLG_EDIT2,6,55,216,49,
                             ES_MULTILINE | ES_AUTOHSCROLL | 
                             ES_WANTRETURN | WS_VSCROLL
    DEFPUSHBUTTON   "OK",IDOK,171,4,51,14,WS_GROUP
    PUSHBUTTON      "CANCEL",IDCANCEL,171,21,51,14,WS_GROUP
    LTEXT           "",IDC_STATIC,0,39,8,8,NOT WS_VISIBLE
END

To thoroughly understand this source file, please refer to MSDN (check references below).

However, I would like you to note the following:

  • The numbers which denote the dimensions and positions.
  • The IDXXXX which denote the IDs. Those IDS are defined in the "resource.h" file.
  • The commands "LTEXT", "EDITTEXT", etc... that designate which control to create.
  • The style constants WS_VISIBLE or ES_MULTILINE, or DS_MODALFRAME, etc...

If you're curious about how a .RES file looks like, I have included a small hex dump of this compiled structure here:

Image 3

Here's how a "resource.h" (partial) looks like:

#define IDD_INPUTBOX                    103
#define IDC_INPUTBOX_PROMPT             1000
#define IDC_INPUTBOX_DLG_EDIT1          1001
#define IDC_INPUTBOX_DLG_EDIT2          1002
#define IDC_STATIC                      -1

Please note that the RES file not only describes your dialog, but also all the items in the .RC file (icons, string table, etc...). Since the resource file holds a number of resource items, all defined by certain IDs and resource types, we need a way to select the given resource and use it. That's why we have the FindResource() and other resource management APIs.

This small code will illustrate how to create a dialog whose ID is defined in resource.h as IDD_MYDLG:

#include <windows.h>
#include "resource.h"

int main()
{
  HMODULE hModule = ::GetModuleHandle(0);
  HINSTANCE hInst = hModule;

  HRSRC hrsrc = ::FindResource(hModule, 
                  MAKEINTRESOURCE(IDD_MYDLG), RT_DIALOG);

  HGLOBAL hglobal = ::LoadResource(hModule, hrsrc);

  ::DialogBoxIndirectParam(hInst, 
                  (LPCDLGTEMPLATE) hglobal, 0, 0, 0);

  return 0;
}

Notice how we pass the "hglobal" as "LPCDLGTEMPLATE". This is the pointer to the compiled dialog template as discussed earlier. This code doesn't pass a dialog procedure, thus the dialog will not respond to the Close messages or anything like that, and you will have to kill the process or write an appropriate dialog procedure.

A simple dialog procedure which we can write is:

LRESULT CALLBACK dlgProc(HWND hDlg, UINT Msg, 
                 WPARAM wParam, LPARAM lParam)
{
  switch (Msg)
  {
    case WM_CLOSE:
      ::EndDialog(hDlg, IDOK);
      return TRUE;
  }
  return 0;
}

And then we adjust the call to:

::DialogBoxIndirectParam(hInst, (LPCDLGTEMPLATE) hglobal, 
                                   0, (DLGPROC)dlgProc, 0);

The DlgResToDlgTemplate tool

In the course of writing the Win32Inputbox library, I developed a small tool named "DlgResToDlgTemplate". This tool's sole purpose is to fetch a dialog resource from a binary (which is now in compiled form) and dump it as a C character array. After extracting the dialog template, we can employ it in our own application.

A quick example would be, employing the NOTEPAD.EXE template in our own simple application.

  • Extract the template from notepad.exe using:
    DlgResToDlgTemplate.exe d:\windows\system32\notepad.exe 14 n.h
    DlgResToDlgTemplate v1.0 (c) <lallousx86@yahoo.com>
    
    generated n.h (1195 bytes) successfully!
  • Now that we have the "n.h" which is the dialog template of the notepad.exe "Goto line" dialog, we can modify the sample code (mentioned above) as:
    static unsigned char dlg_14[] = 
    {
        0xc0,0x20,0xc8,0x80,0x00,0x00,0x00,0x00,
        0x04,0x00,0x00,0x00,0x00,0x00,0xb4,0x00,0x39,
        0x00,0x00,0x00,0x00,0x00,0x47,0x00,0x6f,
        0x00,0x74,0x00,0x6f,0x00,0x20,0x00,0x6c,
        0x00,0x69,0x00,0x6e,0x00,0x65,0x00,0x00,
        0x00,0x08,0x00,0x4d,0x00,0x53,0x00,0x20,
        0x00,0x53,0x00,0x68,0x00,0x65,0x00,0x6c,
        0x00,0x6c,0x00,0x20,0x00,0x44,0x00,0x6c,
        0x00,0x67,0x00,0x00,0x00,0x00,0x00,0x00,
        0x00,0x02,0x50,0x00,0x00,0x00,0x00,0x07,
        0x00,0x09,0x00,0x32,0x00,0x0a,0x00,0xb0,
        0x04,0xff,0xff,0x82,0x00,0x26,0x00,0x4c,
        0x00,0x69,0x00,0x6e,0x00,0x65,0x00,0x20,
        0x00,0x4e,0x00,0x75,0x00,0x6d,0x00,0x62,
        0x00,0x65,0x00,0x72,0x00,0x3a,0x00,0x00,
        0x00,0x00,0x00,0x80,0x00,0x81,0x50,0x00,
        0x00,0x00,0x00,0x37,0x00,0x07,0x00,0x39,
        0x00,0x0c,0x00,0x02,0x01,0xff,0xff,0x81,
        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,
        0x00,0x01,0x50,0x00,0x00,0x00,0x00,0x07,
        0x00,0x22,0x00,0x32,0x00,0x0e,0x00,0x01,
        0x00,0xff,0xff,0x80,0x00,0x4f,0x00,0x4b,
        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
        0x00,0x01,0x50,0x00,0x00,0x00,0x00,0x4e,
        0x00,0x22,0x00,0x32,0x00,0x0e,0x00,0x02,
        0x00,0xff,0xff,0x80,0x00,0x43,0x00,0x61,
        0x00,0x6e,0x00,0x63,0x00,0x65,0x00,0x6c,
        0x00,0x00,0x00,0x00,0x00
    };
        
    void show_template_dlg()
    {
      ::DialogBoxIndirectParam((HINSTANCE) ::GetModuleHandle(0), 
                  (LPCDLGTEMPLATE) dlg_14, 0, (DLGPROC)dlgProc, 0);
    }

Hope everything's clear so far. Next, we will see how practical it is to use the dialog templates to create small (self-contained) functions.

CWin32InputBox class overview

Now we can talk about the construction of the CWin32Inputbox class, after having introduced all the concepts needed for this task.

In a nutshell, CWin32InputBox::InputBox():

  1. Defines a proper dialog procedure to handle the OK and CANCEL buttons.
  2. Defines a WM_INITDIALOG handler to properly initialize the dialog.
  3. Having the dialog template needed, named as "definputbox_dlg", we can:
    1. Call DialogBoxIndirectParam() to show the dialog.
    2. Do some actions based on the return value of the modal dialog.

The class exports the two static methods:

static INT_PTR InputBoxEx(WIN32INPUTBOX_PARAM *);
static INT_PTR InputBox(LPCTSTR szTitle, 
                        LPCTSTR szPrompt, 
                        LPTSTR szResult, 
                        DWORD nResultSize,
                        bool bMultiLine = false,
                        HWND hwndParent = 0);

You may simply call the InputBox method as:

CWin32InputBox::InputBox("hello", "what?", buf, 100, false);

to produce something like:

Image 4

The extended version uses the WIN32INPUTBOX_PARAM structure to allow you to customize the input box. So to use this class in your project, all you have to do is simply add the "Win32InputBox.cpp/.h" to your project. No need for resources or anything.

You may freely use the code under the zlib/libpng license; check the "Win32InputBox.h" file.

Points of interest

It was fun learning about dialog templates and more fun to write the reusable CWin32InputBox class. Hope you enjoyed and learned from this article. If you give me a low rating, I'd appreciate dropping me a comment and telling me how I can improve my article.

Before closing this article, I'd like to give a small tip for those who don't know: you can use your Visual Studio IDE to peek around other binary file resources'! Just press CTRL+O, locate a Win32 PE file, and open it!

References

  • MSDN -> Win32 and COM Development -> Tools -> Platform SDK Tools -> SDK Tools -> Resource Tools -> Resource Compiler -> Resource Definition Statements.
  • MSDN -> CreateWindowEx() function.
  • MSDN -> Using Resources.
  • MSDN -> DLGTEMPLATEEX structure.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
United States United States
Elias (aka lallousx86, @0xeb) has always been interested in the making of things and their inner workings.

His computer interests include system programming, reverse engineering, writing libraries, tutorials and articles.

In his free time, and apart from researching, his favorite reading topics include: dreams, metaphysics, philosophy, psychology and any other human/mystical science.

Former employee of Microsoft and Hex-Rays (the creators of IDA Pro), was responsible about many debugger plugins, IDAPython project ownership and what not.

Elias currently works as an Anticheat engineer in Blizzard Entertainment.

Elias co-authored 2 books and authored one book:

- Practical Reverse Engineering
- The Antivirus Hacker's Handbook
- The Art of Batch Files Programming

Comments and Discussions

 
GeneralRe: Some changes for numeric inputbox Pin
Ryan Dines21-Jun-11 14:58
Ryan Dines21-Jun-11 14:58 
GeneralRe: Some changes for numeric inputbox Pin
Chriistophe14-Feb-20 0:12
Chriistophe14-Feb-20 0:12 
Questionhow to make it converte to char like i want what i type in the input box to char* Pin
neoncore27-Aug-08 15:51
neoncore27-Aug-08 15:51 
GeneralWhere is the ICON information stored Pin
tony metters7-Apr-08 3:34
tony metters7-Apr-08 3:34 
GeneralRe: Where is the ICON information stored Pin
Elias Bachaalany15-Apr-08 2:45
Elias Bachaalany15-Apr-08 2:45 
Generalcompile error Pin
Matt Davison28-Jan-08 6:39
Matt Davison28-Jan-08 6:39 
Generalfun stuff! Pin
min_2_max25-Dec-07 19:45
min_2_max25-Dec-07 19:45 
Generalthank u, great joy! Pin
Mitnk4-Aug-07 23:15
Mitnk4-Aug-07 23:15 
Generalpassword Pin
vb6comm8931-Aug-06 22:52
vb6comm8931-Aug-06 22:52 
GeneralRe: password Pin
Elias Bachaalany31-Aug-06 23:04
Elias Bachaalany31-Aug-06 23:04 
GeneralGreat article Pin
george pappas8-Jun-06 2:11
george pappas8-Jun-06 2:11 
GeneralRe: Great article Pin
Elias Bachaalany8-Jun-06 2:20
Elias Bachaalany8-Jun-06 2:20 
GeneralRe: Great article Pin
Elias Bachaalany8-Jun-06 2:23
Elias Bachaalany8-Jun-06 2:23 
GeneralRe: Great article Pin
george pappas8-Jun-06 6:42
george pappas8-Jun-06 6:42 
GeneralRe: Great article Pin
Elias Bachaalany8-Jun-06 20:43
Elias Bachaalany8-Jun-06 20:43 
GeneralRe: Great article Pin
george pappas9-Jun-06 7:31
george pappas9-Jun-06 7:31 
GeneralRe: Great article Pin
_WilliamK_23-Jul-08 6:57
_WilliamK_23-Jul-08 6:57 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.