Windows API对话框不使用资源文件

时间:2008-09-14 20:46:20

标签: c++ winapi dialog

我正在尝试使用C ++和Windows API创建一个对话框,但我不希望在资源文件中定义对话框。我在网上找不到任何好的东西,我读过的所有例子似乎都没有以编程方式定义对话框。

任何人都知道如何做到这一点?一个简单的例子很好,我还没有做任何复杂的事情。

5 个答案:

答案 0 :(得分:14)

答案 1 :(得分:3)

如果您只想显示一个带控件的窗口,则可以在不使用资源(.rc)文件/脚本的情况下创建窗口。

这与对话框不同,但它可能比以编程方式创建对话框更容易。

首先,关于如何做到的一些注意事项:

  • 您可以手动使用JOIN(或CreateWindow)来创建主窗口的子窗口,而不是在rc文件中设计对话框。 (对于.NET Winforms程序员,这些窗口就像CreateWindowEx s)。

  • 此过程根本不是图形化的(您需要手动输入每个窗口的位置和大小),但我认为这可以很好地理解对话框的创建方式。

  • 不使用真正的对话框有一些缺点,即在切换控件时该选项卡不起作用。

关于示例:

  • 此示例的对话框包含两个按钮,一个编辑框(.NET winforms程序员会将其视为Control)和一个复选框。

Screenshot of window

已在以下条件下进行测试:

  • x86 build
  • x64 build
  • Unicode版本(TextBoxUNICODE已定义)
  • 非unicode构建(_UNICODEUNICODE未定义)
  • 使用Visual Studio的C编译器构建
  • 使用Visual Studio的C ++编译器构建
  • 操作系统:Windows 10 64位

现在代码:

请注意,添加了大量注释以尝试记录Windows函数,我建议将其复制/粘贴到文本编辑器中,以获得最佳效果。

_UNICODE

进一步阅读

内置的窗口类集非常有限,因此您可能会对如何使用winapi定义自己的窗口类(“// This sample will work either with or without UNICODE, it looks like it's recommended now to use // UNICODE for all new code, but I left the ANSI option in there just to get the absolute maximum // amount of compatibility. // // Note that UNICODE and _UNICODe go together, unfortunately part of the Windows API // uses _UNICODE, and part of it uses UNICODE. // // tchar.h for example, makes heavy use of _UNICODE, and windows.h makes heavy use of UNOCODE. #define UNICODE #define _UNICODE //#undef UNICODE //#undef _UNICODE #include <windows.h> #include <tchar.h> // I made this struct to more conveniently store the positions / size of each window in the dialog typedef struct SizeAndPos_s { int x, y, width, height; } SizeAndPos_t; // typically these would be #defines but there is no reason to not make them constants const WORD ID_btnHELLO = 1; const WORD ID_btnQUIT = 2; const WORD ID_CheckBox = 3; const WORD ID_txtEdit = 4; const WORD ID_btnShow = 5; // x, y, width, height const SizeAndPos_t mainWindow = { 150, 150, 300, 300 }; const SizeAndPos_t btnHello = { 20, 50, 80, 25 }; const SizeAndPos_t btnQuit = { 120, 50, 80, 25 }; const SizeAndPos_t chkCheck = { 20, 90, 185, 35 }; const SizeAndPos_t txtEdit = { 20, 150, 150, 20 }; const SizeAndPos_t btnShow = { 180, 150, 80, 25 }; HWND txtEditHandle = NULL; // hwnd: All window processes are passed the handle of the window that they belong to in hwnd. // msg: Current message (e.g., WM_*) from the OS. // wParam: First message parameter, note that these are more or less integers but they are really just "data chunks" that you are expected to memcpy as raw data to float, etc. // lParam: Second message parameter, same deal as above. LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { case WM_CREATE: // Create the buttons //------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ // note that the "parent window" is the dialog itself. Since we are in the dialog's WndProc, the dialog's handle is passed into hwnd. // //CreateWindow( lpClassName, lpWindowName, dwStyle, x, y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam //CreateWindow( windowClassName, initial text, style (flags), xPos, yPos, width, height, parentHandle, menuHandle, instanceHandle, param); CreateWindow( TEXT("Button"), TEXT("Hello"), WS_VISIBLE | WS_CHILD, btnHello.x, btnHello.y, btnHello.width, btnHello.height, hwnd, (HMENU)ID_btnHELLO, NULL, NULL); CreateWindow( TEXT("Button"), TEXT("Quit"), WS_VISIBLE | WS_CHILD, btnQuit.x, btnQuit.y, btnQuit.width, btnQuit.height, hwnd, (HMENU)ID_btnQUIT, NULL, NULL); // Create a checkbox //------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ CreateWindow( TEXT("button"), TEXT("CheckBox"), WS_VISIBLE | WS_CHILD | BS_CHECKBOX, chkCheck.x, chkCheck.y, chkCheck.width, chkCheck.height, hwnd, (HMENU)ID_CheckBox, NULL, NULL); // Create an edit box (single line text editing), and a button to show the text //------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ //Handle = CreateWindow(windowClassName, windowName, style, xPos, yPos, width, height, parentHandle, menuHandle, instanceHandle, param); txtEditHandle = CreateWindow(TEXT("Edit"), TEXT("Initial Text"), WS_CHILD | WS_VISIBLE | WS_BORDER, txtEdit.x, txtEdit.y, txtEdit.width, txtEdit.height, hwnd, (HMENU)ID_txtEdit, NULL, NULL); //CreateWindow( windowClassName, windowName, style, xPos, yPos, width, height, parentHandle, menuHandle, instanceHandle, param); CreateWindow( TEXT("Button"), TEXT("Show"), WS_VISIBLE | WS_CHILD, btnShow.x, btnShow.y, btnShow.width, btnShow.height, hwnd, (HMENU)ID_btnShow, NULL, NULL); // Create an Updown control. Note that this control will allow you to type in non-number characters, but it will not affect the state of the control break; //For more information about WM_COMMAND, see https://msdn.microsoft.com/en-us/library/windows/desktop/ms647591(v=vs.85).aspx case WM_COMMAND: // the LOWORD of wParam identifies which control sent the WM_COMMAND message. The WM_COMMAND message is sent when the button has been clicked if (LOWORD(wParam) == ID_btnHELLO) { MessageBox(hwnd, TEXT("Hello!"), TEXT("Hello"), MB_OK); } else if (LOWORD(wParam) == ID_btnQUIT) { PostQuitMessage(0); } else if (LOWORD(wParam) == ID_CheckBox) { UINT checked = IsDlgButtonChecked(hwnd, ID_CheckBox); if (checked) { CheckDlgButton(hwnd, ID_CheckBox, BST_UNCHECKED); MessageBox(hwnd, TEXT("The checkbox has been unchecked."), TEXT("CheckBox Event"), MB_OK); } else { CheckDlgButton(hwnd, ID_CheckBox, BST_CHECKED); MessageBox(hwnd, TEXT("The checkbox has been checked."), TEXT("CheckBox Event"), MB_OK); } } else if (LOWORD(wParam) == ID_btnShow) { int textLength_WithNUL = GetWindowTextLength(txtEditHandle) + 1; // WARNING: If you are compiling this for C, please remember to remove the (TCHAR*) cast. TCHAR* textBoxText = (TCHAR*) malloc(sizeof(TCHAR) * textLength_WithNUL); GetWindowText(txtEditHandle, textBoxText, textLength_WithNUL); MessageBox(hwnd, textBoxText, TEXT("Here's what you typed"), MB_OK); free(textBoxText); } break; case WM_DESTROY: PostQuitMessage(0); break; } return DefWindowProc(hwnd, msg, wParam, lParam); } // hInstance: This handle refers to the running executable // hPrevInstance: Not used. See https://blogs.msdn.microsoft.com/oldnewthing/20040615-00/?p=38873 // lpCmdLine: Command line arguments. // nCmdShow: a flag that says whether the main application window will be minimized, maximized, or shown normally. // // Note that it's necesary to use _tWinMain to make it so that command line arguments will work, both // with and without UNICODE / _UNICODE defined. int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { MSG msg; WNDCLASS mainWindowClass = { 0 }; mainWindowClass.lpszClassName = TEXT("JRH.MainWindow"); // you can set the main window name to anything, but typically you should prefix custom window classes with something that makes it unique. mainWindowClass.hInstance = hInstance; mainWindowClass.hbrBackground = GetSysColorBrush(COLOR_3DFACE); mainWindowClass.lpfnWndProc = WndProc; mainWindowClass.hCursor = LoadCursor(0, IDC_ARROW); RegisterClass(&mainWindowClass); // Notes: // - The classname identifies the TYPE of the window. Not a C type. This is a (TCHAR*) ID that Windows uses internally. // - The window name is really just the window text, this is commonly used for captions, including the title bar of the window itself. // - parentHandle is considered the "owner" of this window. MessageBoxes can use HWND_MESSAGE to free them of any window. // - menuHandle: hMenu specifies the child-window identifier, an integer value used by a dialog box control to notify its parent about events. // The application determines the child-window identifier; it must be unique for all child windows with the same parent window. //CreateWindow( windowClassName, windowName, style, xPos, yPos, width, height, parentHandle, menuHandle, instanceHandle, param); CreateWindow( mainWindowClass.lpszClassName, TEXT("Main Window"), WS_OVERLAPPEDWINDOW | WS_VISIBLE, mainWindow.x, mainWindow.y, mainWindow.width, mainWindow.height, NULL, 0, hInstance, NULL); while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return (int)msg.wParam; } // This code is based roughly on tutorial code present at http://zetcode.com/gui/winapi/ s”)感到好奇,请参阅以下文章:

  

注意:我最初打算这篇文章以编程方式介绍对话框的创建。由于我的错误,我没有意识到你不能只是“显示”窗口作为对话框。不幸的是,我无法得到Raymond Chen提到的设置。

答案 2 :(得分:2)

看一下这个toolkit,它描述了如何创建没有资源文件的对话框。它是在WTL中,但是我确信你可以直接使用win32 API来分离内部结构来实现相同的功能。

答案 3 :(得分:1)

尝试在MSDN中搜索“内存中的对话框模板”

请参阅此示例:http://msdn.microsoft.com/en-us/library/ms632588(VS.85).aspx

答案 4 :(得分:1)

萨拉姆,嗨,  在这里,您可以找到如何在不使用资源文件的情况下使用Windows API对话框。  Winapi(C Win32 API,无MFC)教程:http://zetcode.com/gui/winapi/