在win32 API中创建一个容器

时间:2016-07-17 22:40:29

标签: c++ winapi

我是Win32 API的初学者。我正在尝试创建一个需要容器的小应用程序,但我遇到了问题。

在HTML中,我会告诉你我想要什么。它的代码如下:

div{width:120px; height:300px; display:block; overflow-y:auto;}
button{display:list-item;list-style:none; margin-bottom:3px;}
<div class="container">
  <button>button 1</button>
  <button>button 2</button>
  <button>button 3</button>
  <button>button 4</button>
  <button>button 5</button>
  <button>button 6</button>
  <button>button 7</button>
  <button>button 8</button>
  <button>button 9</button>
  <button>button 10</button>
  <button>button 11</button>
  <button>button 12</button>
  <button>button 13</button>
  <button>button 14</button>
</div>

我尝试使用以下代码在C ++中重复相同的显示:

#include <windows.h>
#include <string>
#include <vector>

const char *ClsName = "classname";
const char *WndName = "Windows";
HINSTANCE hInst;

LRESULT CALLBACK WndProcedure(HWND hWnd, UINT uMsg,
    WPARAM wParam, LPARAM lParam);

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
    LPSTR lpCmdLine, int nCmdShow)
{
    MSG        Msg;
    HWND       hWnd;
    WNDCLASSEX WndClsEx;

    hInst = hInstance;

    // Create the application window
    WndClsEx.cbSize = sizeof(WNDCLASSEX);
    WndClsEx.style = CS_HREDRAW | CS_VREDRAW;
    WndClsEx.lpfnWndProc = WndProcedure;
    WndClsEx.cbClsExtra = 0;
    WndClsEx.cbWndExtra = 0;
    WndClsEx.hIcon = LoadIcon(NULL, IDI_QUESTION);
    WndClsEx.hCursor = LoadCursor(NULL, IDC_ARROW);
    WndClsEx.hbrBackground = (HBRUSH)GetStockObject(WHITE_PEN);
    WndClsEx.lpszMenuName = MAKEINTRESOURCEA(109);
    WndClsEx.lpszClassName = ClsName;
    WndClsEx.hInstance = hInst;

    WndClsEx.hIconSm = LoadIcon(NULL, IDI_QUESTION);
    // Register the application
    RegisterClassEx(&WndClsEx);

    // Create the window object
    hWnd = CreateWindow(ClsName,
        WndName,
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        NULL,
        NULL,
        hInst,
        NULL);

    // Find out if the window was created successfully
    if (!hWnd) // If the window was not created,
        return 0; // stop the application

                  // Display the window to the user
    ShowWindow(hWnd, SW_SHOWNORMAL);
    UpdateWindow(hWnd);

    // Decode and treat the messages
    // as long as the application is running
    while (GetMessage(&Msg, NULL, 0, 0))
    {
        TranslateMessage(&Msg);
        DispatchMessage(&Msg);
    }

    return Msg.wParam;
};
//classname

//classname
using namespace std;

 LRESULT CALLBACK WndProcedure(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
     static HWND ws[50], st, sd;
     switch (msg) {
     case WM_DESTROY:
         PostQuitMessage(0); break;
     case WM_CREATE:
         sd = CreateWindow(ClsName, NULL, WS_CHILD | WS_VSCROLL |WS_HSCROLL| WS_BORDER | WS_VISIBLE, 10, 10, 200, 600, hwnd, NULL, hInst, NULL);//Container
         for (int i = 0; i < 114; i++) {
         ws[i] = CreateWindow("Button", ("Button" + to_string(i)).c_str(), WS_VISIBLE | WS_BORDER | WS_CHILD, 10, 25*i + 10, 150, 20, sd, (HMENU)(i + 1), hInst, NULL); //Buttons
         };      
         break;
     default: return DefWindowProc(hwnd, msg, wparam, lparam); break;
     }
 }

使用这段代码,我得到一个在主窗口中无限重复的容器。

这是结果的屏幕截图;

image

我不明白结果。似乎我使用了一个循环,但我没有。

2 个答案:

答案 0 :(得分:2)

  

似乎我使用了循环,但我没有。

实际上,你做到了。您的WM_CREATE消息处理程序中有递归循环

您的WinMain()来电CreateWindow()来创建初始ClsName窗口,然后您的WM_CREATE处理程序调用{​​{1}}来创建另一个 CreateWindow()窗口(对其邮件使用相同的ClsName)。当第二个窗口收到WndProcedure()时,您正在调用WM_CREATE来创建另一个 CreateWindow()窗口。还有另一个ClsName窗口,依此类推。

请勿在早期ClsName窗口的ClsName内创建新的WM_CREATE窗口。您已定义了ClsName类名,但您没有注册或使用它。也许你打算这样做。或者,对容器使用标准STATIC control

此外,您的WndName邮件处理程序还有另一个错误。它创建了114个子按钮,但是将它们存储在一个只能容纳50 WM_CREATE s的静态数组中。因此,您有一个缓冲区溢出会破坏内存。

答案 1 :(得分:0)

好的,首先,我认为你的意思是WM_CREATE(不是VM_CREATE) - 你发布了实际的代码吗?因为我怀疑这是否有效。

其次,WM_CREATE是您在调用CreateWindow后由Windows发送给您的消息。在这里看到doco: https://msdn.microsoft.com/en-us/library/windows/desktop/ms632619(v=vs.85).aspx

在你的情况下,你将创建一个无限循环的窗口创建,然后是通知消息。