我試圖創建一個WINAPI窗口創一流動態創建按鈕..在WINAPI
我堅持搞清楚如何讓窗口動態地添加控件,併爲他們註冊的消息。
#include <windows.h>
#include <iostream>
#include <vector>
#include <tuple>
#include <thread>
using namespace std;
class WinForm
{
private:
HWND WindowHandle = nullptr;
std::thread Thread;
std::vector<std::tuple<std::string, std::size_t, HWND>> ControlHandles;
public:
~WinForm();
WinForm(std::string ClassName, std::string WindowName, bool Threaded = false, int Width = CW_USEDEFAULT, int Height = CW_USEDEFAULT, WNDPROC WindowProcedure = nullptr, WNDCLASSEX WndClass = {0});
bool AddButton(std::string ButtonName, POINT Location, int Width, int Height);
};
WinForm::~WinForm()
{
if (Thread.joinable())
{
Thread.join();
}
}
WinForm::WinForm(std::string ClassName, std::string WindowName, bool Threaded, int Width, int Height, WNDPROC WindowProcedure, WNDCLASSEX WndClass)
{
if (WindowProcedure == nullptr)
{
WindowProcedure = [](HWND window, UINT msg, WPARAM wp, LPARAM lp) -> LRESULT __stdcall
{
switch(msg)
{
case WM_PAINT:
break;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
default:
return DefWindowProc(window, msg, wp, lp);
}
return 0;
};
}
if (WndClass.cbSize == 0)
{
WndClass =
{
sizeof(WNDCLASSEX), CS_DBLCLKS, WindowProcedure,
0, 0, GetModuleHandle(nullptr), LoadIcon(nullptr, IDI_APPLICATION),
LoadCursor(nullptr, IDC_ARROW), HBRUSH(COLOR_WINDOW+1),
nullptr, ClassName.c_str(), LoadIcon (nullptr, IDI_APPLICATION)
};
}
if (RegisterClassEx(&WndClass))
{
if (Threaded)
{
Thread = std::thread([ClassName, WindowName, Width, Height, this]{
WindowHandle = CreateWindowEx(0, ClassName.c_str(), WindowName.c_str(), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, Width, Height, nullptr, nullptr, GetModuleHandle(nullptr), nullptr);
if(WindowHandle)
{
MSG msg = {nullptr};
ShowWindow(WindowHandle, SW_SHOWDEFAULT);
while(GetMessage(&msg, nullptr, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
});
}
else
{
WindowHandle = CreateWindowEx(0, ClassName.c_str(), WindowName.c_str(), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, Width, Height, nullptr, nullptr, GetModuleHandle(nullptr), nullptr);
if(WindowHandle)
{
MSG msg = {nullptr};
ShowWindow(WindowHandle, SW_SHOWDEFAULT);
while(GetMessage(&msg, nullptr, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
}
}
}
bool WinForm::AddButton(std::string ButtonName, POINT Location, int Width, int Height)
{
for (std::vector<std::tuple<std::string, std::size_t, HWND>>::iterator it = ControlHandles.begin(); it != ControlHandles.end(); ++it)
{
if (ButtonName == std::get<0>(*it))
{
return false;
}
}
std::size_t ID = 1;
for (std::vector<std::tuple<std::string, std::size_t, HWND>>::iterator it = ControlHandles.begin(); it != ControlHandles.end(); ++it, ++ID)
{
if (std::get<1>(*it) != ID)
{
break;
}
}
HWND ButtonHandle = CreateWindowEx(0, "Button", ButtonName.c_str(), WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, Location.x, Location.y, Width, Height, WindowHandle, (HMENU)ID, GetModuleHandle(nullptr), nullptr);
ControlHandles.push_back(std::make_tuple(ButtonName, ID, ButtonHandle));
SendMessage(WindowHandle, WM_CREATE, 0, 0);
return true;
}
int main()
{
WinForm Form("Class", "Title", true);
Form.AddButton("NewButton", {50, 50}, 25, 25);
}
在上面,它編譯得很好,並顯示窗口就好了..它只是不顯示我試圖動態添加到窗口的按鈕。有沒有人有任何想法,我可以動態地添加按鈕到窗口,並允許按鈕註冊消息?
這不太可能是你的問題的原因,但我沒有理由在創建按鈕後發送'WM_CREATE'消息。 – chris 2013-03-06 14:49:46
@chris不僅沒有理由,它明確地被禁止。系統發送'WM_CREATE'作爲創建的一部分。如果你手動發送,那麼你[惡作劇 - 調用窗口](http://blogs.msdn.com/b/oldnewthing/archive/2011/09/26/10216420.aspx)。 – 2013-03-06 15:20:36
@RaymondChen,我對'WM_DESTROY'有些意識,但沒有'WM_CREATE'。我也認爲我以前不知道該怎麼讀:) – chris 2013-03-06 15:46:29