如何使用WinAPI在C++中创建带有标签的spinbox的窗口

You*_*008 0 c++ windows user-interface winapi

我花了一天的时间试图让这个工作变得如此简单: 纺纱器

我所需要的只是能够以编程方式获取值,设置值,当然还允许用户通过写入字段或按箭头来设置值.MSDN对此非常麻烦,并没有提供足够的信息如何工作.在互联网的其他部分,没有代码可以做的工作示例.

我正在使用Windows 7中的MinGW编译程序,我需要它在Windows 7及更高版本上运行.无论是否使用程序Win32 API或MFC编写都没关系.

编辑: 经过一番讨论,我意识到我忘了指出重要的事实.我真的只是编写一个非常简单的应用程序,它将包含不超过3个小部件,我不打算将来使用Win32 API.因此,我没有理由学习所有这些特定于Windows的机制,并遵循MSDN强大的方法,使用资源文件中的自定义对话框定义或在内存中构建.

有没有办法,怎么做没有资源文件,自定义对话框类,并尽可能少的代码行?如何在现有窗口中直接创建一个spinbox以及我需要处理哪些消息?

Cod*_*ray 7

你在这些链接方面的括号评论在我的脑海中留下了一些不好的印象.不,当然他们"不可编辑".文档的目的不是为您提供完全编写和完善的代码,您只需将其放入项目中即可.MSDN文章试图让您了解上下控件的工作原理,并且具备您对Win32 API的背景知识,应该足以让它们在您的项目中工作.

公平地说,您链接的Dr. Dobbs文章关于16位Windows,这是一个与32位Windows不同的编程环境,所以如果您还不是Win32专家,这可能不是一个很好的参考你可以发现差异.其中一些是微妙的.

另外,我在上面提到了"你对Win32 API的背景知识".这很重要.如果要进行Windows编程,则需要了解Windows编程.通过将来自网络各个地方的代码示例拼凑在一起,您不会成功.这种方式很少编程,但肯定不是复杂的C API.学习Win32的标准资源是Charles Petzold 编程Windows的第5版.由于您需要第5版(不是更新版),所以在亚马逊上经常以低价购买使用过的副本.

初步的开头,我打算回答你的问题.当你说你想要创建一个"窗口"时,这有点模棱两可,因为在Windows编程语言中,一切都是窗口.这些控件中的每一个实际上都是Windows,它们可以托管在本身就是窗口的容器上,并且该容器可以托管在对话框或顶级窗口上.所以我不清楚你想要最终产品的样子.

我猜你可能想要一个包含这些控件的对话框(当然是一个窗口).使用对话框可以非常简单,因为您可以使用资源编辑器以图形方式布置包含所需控件的对话框.Visual Studio编程环境附带内置资源编辑器,但如果您愿意,可以使用第三方解决方案.ResEditResource Hacker是可靠的选择.当然,您需要阅读文档以了解如何使这些工具为您工作.最终,他们将要做的是生成一个对话框模板,该模板存储在资源文件中并链接到您的二进制文件中.示例对话框模板如下所示:

IDD_DIALOG1 DIALOGEX 0, 0, 238, 54
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Dialog"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
    LTEXT           "&Month:",IDC_STATIC,7,9,30,8
    EDITTEXT        IDC_MONTH,37,7,40,14,ES_AUTOHSCROLL
    CONTROL         "",IDC_MONTH_SPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS,63,15,11,14
    LTEXT           "&Day:",IDC_STATIC,84,9,30,8
    EDITTEXT        IDC_DAY,114,7,40,14,ES_AUTOHSCROLL
    CONTROL         "",IDC_DAY_SPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS,140,16,11,14
    LTEXT           "&Year",IDC_STATIC,161,9,30,8
    EDITTEXT        IDC_YEAR,191,7,40,14,ES_AUTOHSCROLL
    CONTROL         "",IDC_YEAR_SPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS,217,16,11,14
    DEFPUSHBUTTON   "OK",IDOK,127,32,50,14
    PUSHBUTTON      "Cancel",IDCANCEL,181,32,50,14
END
Run Code Online (Sandbox Code Playgroud)

请注意,正如MSDN文档所述,Up-Down控件实际上只是一个小微调框.您需要将其附加到文本框(编辑控件)以使其有用.微调框将自动与Z顺序中的编辑控件混在一起.这大大简化了代码,但是如果您愿意,可以使用API​​来操作控件以手动实现相同的效果.MSDN文档解释了如何.

一旦定义了此对话框模板并将其设置为链接到项目中,就可以通过简单调用该DialogBox函数来显示该对话框.在上面的代码中,我给对话框指定了符号名称IDD_DIALOG1; 这应该在资源头文件中定义,该文件可以全局访问,包括常规代码和资源编译器.

您还需要定义一个对话框过程来处理对话框的消息.消息处理是远远太多,我或其他任何人在简单的文章/答案解释.这是您需要咨询Petzold或其他一般Win32编程资源以填补空白的地方.

#define WIN32_LEAN_AND_MEAN
#include <Windows.h>        // include Windows SDK headers
#include <commctrl.h>
#include <tchar.h>
#include "resource.h"       // include resource definitions

INT_PTR CALLBACK Dialog1Proc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg)
    {
      case WM_INITDIALOG:
      {
           return (INT_PTR)TRUE;
      }
      case WM_COMMAND:
      {
         switch (LOWORD(wParam))
         {
            case IDOK:
            case IDCANCEL:
            {
               EndDialog(hwndDlg, LOWORD(wParam));
               return (INT_PTR)TRUE;
            }
            default:
            {
               break;
            }
         }
         break;
      }
    }
    return (INT_PTR)FALSE;
}

int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE, LPTSTR, int nCmdShow)
{
   // Initialize the common controls at the start of your application.
   INITCOMMONCONTROLSEX iccex;
   iccex.dwSize = sizeof(iccex);
   iccex.dwICC  = ICC_WIN95_CLASSES;

    // Show the dialog box.
    // This creates a modal dialog box that runs its own message loop,
    // and thus does not require your code to have its own.
    // A modal dialog box is therefore *blocking*, and this function call
    // does not return until the dialog box has been dismissed.
    DialogBox(hInstance,   // handle to instance that contains your resources (probably your EXE)
              MAKEINTRESOURCE(IDD_DIALOG1),
              NULL,        // handle to parent window of dialog, or NULL if no parent
              Dialog1Proc  // pointer to dialog's window procedure
             );
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

这将在屏幕上显示对话框:

但乐趣才刚刚开始!您可能希望在对话框的窗口过程中编写代码来处理某些消息并控制对话框的行为.上下控件可以更改文本框中显示的整数值,但您可能需要设置可接受的范围.或者您可能想要反转最大值和最小值,以便底部箭头递减值而不是递增它(出于兼容性原因,这种异常和意外行为是默认行为).

如果您希望实际上想要检索用户在文本框中输入的值,那么您还需要做更多的工作.一个基本策略是检索值以响应WM_DESTROY消息并将它们存储在可以从调用者读取的位置.当然,有更好的方法可以做到这一点,使用C++面向对象的包装使它更容易,但它更先进,需要一些关于Windows编程如何工作的基本知识.

值得指出的是,如果由于某种原因无法使用对话框模板,或者您想要创建标准窗口,您还可以编写通过调用该CreateWindowEx函数手动创建这些单独窗口的代码.这就是您链接的MSDN文章试图描述的内容.它确实有效,而且更灵活,但也更复杂.老实说,你应该能够通过阅读MSDN文章来解决这个问题.这是非常完整和相当好的解释,我将授予的并不总是你在MSDN上看到的,但这不是这些情况之一.