Using Dialog Templates to create an InputBox() in C++
2013-04-25 16:17
1226 查看
Download source - 100 Kb
(Single line input box)
(Multi-line input box)
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
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
that is similar to VB's
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.
Currently, to create a dialog box driven application, you have many choices. I'll list the most popular methods:
MFC dialog based application (can be generated by the wizard).
Plain Win32 API - using the IDE's dialog designer.
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):
The design part:
We start by designing our dialog with the editor.
We create controls (buttons, textboxes, ...).
We assign IDs to the controls.
The coding part:
We write our
to our dialog.
We call the appropriate dialog creation method (
or
If you are not using the dialog designer, you will have to create the controls in the code by calling the
As for MFC dialog based applications, the concept is similar, however everything is wrapped into neat classes. So, all you have to do is:
Design the dialog using the editor.
Subclass
Bind your subclassed class to the desired dialog ID.
Overwrite the needed
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
found in the Windows headers. There is an extended version of this structure that renders the latter obsolete. The
not defined anywhere in the header files, but is described in the MSDN. The extended dialog template (
is newer, and introduces more features.
A dialog template alone is enough to describe the dialog, but not the dialog items, thus the
These
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
described in a .RC file:
Collapse | Copy
Code
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
file.
The commands "
etc... that designate which control to create.
The style constants
or
If you're curious about how a .RES file looks like, I have included a small hex dump of this compiled structure here:
Here's how a "resource.h" (partial) looks like:
Collapse | Copy
Code
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
APIs.
This small code will illustrate how to create a dialog whose ID is defined in resource.h as
Collapse | Copy
Code
Notice how we pass the "
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:
Collapse | Copy
Code
And then we adjust the call to:
Collapse | Copy
Code
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:
Collapse | Copy
Code
Collapse | Copy
Code
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:
Collapse | Copy
Code
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.
Now we can talk about the construction of the
for this task.
In a nutshell,
Defines a proper dialog procedure to handle the OK and CANCEL buttons.
Defines a
Having the dialog template needed, named as "
Call
Do some actions based on the return value of the modal dialog.
The class exports the two
Collapse | Copy
Code
You may simply call the
Collapse | Copy
Code
to produce something like:
The extended version uses the
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.
It was fun learning about dialog templates and more fun to write the reusable
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!
MSDN -> Win32 and COM Development -> Tools -> Platform SDK Tools -> SDK Tools -> Resource Tools -> Resource Compiler -> Resource Definition Statements.
MSDN ->
MSDN -> Using Resources.
MSDN ->
(Single line input box)
(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 prettyjob by giving us the
MessageBox()function but nothing like the
InputBoxfunction.
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:MFC dialog based application (can be generated by the wizard).
Plain Win32 API - using the IDE's dialog designer.
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):
The design part:
We start by designing our dialog with the editor.
We create controls (buttons, textboxes, ...).
We assign IDs to the controls.
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:
Design the dialog using the editor.
Subclass
CDialog, say as
CMyDialog.
Bind your subclassed class to the desired dialog ID.
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 DLGTEMPLATEstructure
found in the Windows headers. There is an extended version of this structure that renders the latter obsolete. The
DLGTEMPLATEEXis
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/EXstructures.
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
DLGTEMPLATEand
DLGITEMTEMPLATEare
described in a .RC file:
Collapse | Copy
Code
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
IDXXXXwhich 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_VISIBLEor
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:
Here's how a "resource.h" (partial) looks like:
Collapse | Copy
Code
#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:
Collapse | Copy
Code
#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:
Collapse | Copy
Code
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:
Collapse | Copy
Code
::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 extractingthe 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:
Collapse | Copy
Code
DlgResToDlgTemplate.exe d:\windows\system32\notepad.exe 14 n.h
Collapse | Copy
Code
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:
Collapse | Copy
Code
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 CWin32Inputboxclass, after having introduced all the concepts needed
for this task.
In a nutshell,
CWin32InputBox::InputBox():
Defines a proper dialog procedure to handle the OK and CANCEL buttons.
Defines a
WM_INITDIALOGhandler to properly initialize the dialog.
Having the dialog template needed, named as "
definputbox_dlg", we can:
Call
DialogBoxIndirectParam()to show the dialog.
Do some actions based on the return value of the modal dialog.
The class exports the two
staticmethods:
Collapse | Copy
Code
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
InputBoxmethod as:
Collapse | Copy
Code
CWin32InputBox::InputBox("hello", "what?", buf, 100, false);
to produce something like:
The extended version uses the
WIN32INPUTBOX_PARAMstructure 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 CWin32InputBoxclass. 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 ->
DLGTEMPLATEEXstructure.
转自:http://www.codeproject.com/Articles/13330/Using-Dialog-Templates-to-create-an-InputBox-in-C
相关文章推荐
- How to create a resizeable dialog box with scroll bars in Visual C++
- Write a method to print the last K lines of an input file using C++
- how to create an explorer interface on a dialog using the MFC
- How to create an XTR file from XML in Delphi XE4 using XML Mapper?(delphi中如何通过xmlmapper创建xtr文件)
- spring webservice 搭建出现的异常处理。异常: NAMESPACE_ERR: An attempt is made to create or change an object in a way whi
- Create Custom Modal Dialog Windows For User Input In Oracle Forms
- NAMESPACE_ERR: An attempt is made to create or change an object in a way which is incorrect with regard to namespaces.
- How to use an ActiveX script task to create a loop in DTS
- How to find size of array in C/C++ without using sizeof ?
- An example to create JOB in SQL Server
- 如何在C++中使用VBScript(使用Qt)--How to use VBScript in C++ (Using Qt)
- SecurityException: Binder invocation to an incorrect interface using in-app billing
- An Insight to References in C++
- 【Python错误】windows下使用pip/easy_install提示Fatal error in launcher: Unable to create process using...
- How to call an Oracle Stored Procedure that returns one or more REF CURSORS, using ADO from C++ How
- python pip使用报错:Fatal error in launcher: Unable to create process using '"'
- pip Fatal error in launcher: Unable to create process using
- Python-Fatal error in launcher: Unable to create process using '"'
- How to use toolbar control on dialog using CToolBar class in VC++ - VC++ 中用CToolBar 类如何使用ToolBar控件
- An Introduction to Thread in the upcoming book From: Introduction to the C++ Boost Libraries