我在WinApi中显示Combobox和另一个控件时遇到问题。我试图创建可以帮助我创建应用程序的c ++类。 每个类包含一个控件和基本操作。 所以我创建了主WinApiElement.h类:
#pragma once
#include <windows.h>
class WinApiElement
{
public:
virtual LRESULT CALLBACK InteriorWndProc(HWND hwnd,UINT uMsg, WPARAM wParam, LPARAM lParam) = 0;
static LRESULT CALLBACK StaticWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
HWND handle;
};
其中staticWndProc接收消息并将其定向到InteriorWndProc
(使用GWLP_USERDATA)。类组件继承类WinApiElement
,并包含基本操作:
#pragma once
#include <Windows.h>
#include <Windowsx.h>
#include "WinApiElement.h"
#include "Application.h"
#include "Define.h"
...
class Component : public WinApiElement
{
protected:
int x;
int y;
int width;
int height;
int componentNumber;
bool transparent;
bool mouseHover;
bool LButtonDown;
TRACKMOUSEEVENT trackMouse;
void Create(WinApiElement* Parent, DWORD dwExStyle, LPCSTR nComponent, DWORD ndwStyle, bool parentWndProc, int nleft = 0, int ntop = 0, int nwidth = 200, int nheight = 100);
virtual void WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
public:
LRESULT CALLBACK InteriorWndProc(HWND hwnd,UINT uMsg, WPARAM wParam, LPARAM lParam) override;
Component(WinApiElement* Parent, DWORD dwExStyle, LPCSTR nComponent, DWORD ndwStyle, bool parentWndProc, int nleft = 0, int ntop = 0, int nwidth = 200, int nheight = 100);
~Component();
WinApiElement* parent;
bool setPosition(int newX, int newY);
bool setSize(int newWidth, int newHeight);
bool setLocation(int newX, int newY, int newWidth, int newHeight);
int getX();
bool setX(int newX);
int getY();
bool setY(int newY);
int getWidth();
bool setWidth(int Width);
int getHeight();
bool setHeight(int Height);
void setTransparent(bool newTransparent);
void Repaint();
// Components control metods
virtual void OnResize();
virtual void OnMouseMove(int moveX, int moveY);
virtual void OnMouseLeftDown();
virtual void OnMouseRightDown();
virtual void OnPaint();
virtual void OnMouseEnter();
virtual void OnMouseLeave();
virtual void OnLeftButtonHoldDown();
// -------------------------
void Show(bool value);
void setBorder(bool value);
bool Refresh();
virtual void OnPaint(HWND handle, HDC hdc);
};
此类中的主要功能是Create,因为它设置了WndProc和UserData。
void Component::Create(WinApiElement* Parent, DWORD dwExStyle, LPCSTR nComponent, DWORD ndwStyle, bool parentWndProc, int nleft, int ntop, int nwidth, int nheight)
{
componentNumber = Application::AddComponent();
uindex = componentNumber;
handle = CreateWindowEx(dwExStyle , nComponent, NULL, ndwStyle ,nleft,ntop,nwidth,nheight, Parent->handle, (HMENU) componentNumber, Application::GetInstance(), NULL);
parent = Parent;
wndProc = (LONG_PTR)StaticWndProc;// else wndProc = (LONG_PTR)Parent->StaticWndProc;
transparent = false;
SetLastError(0);
SetWindowLongPtr( handle, GWLP_WNDPROC, (LONG_PTR)wndProc);
if(!(GetLastError() == 0))
{
MessageBox(NULL,"Nie udało się zmienić standardowej funkcji obsługi rozkazu dla kontrolki, nie wszystkie funkcje moga działać poprawnie!","Błąd przy tworzenia komponentu",MB_ICONWARNING);
}
SetLastError(0);
SetWindowLongPtr( handle , GWLP_USERDATA, (LONG_PTR)((WinApiElement*)this) );
if(!(GetLastError() == 0))
{
MessageBox(NULL,"Nie udało się zmienić wskaźnika w komponencie w funkcji setTransparent, nie wszystkie funkcje moga działać poprawnie!","Błąd przy zmienia parametru transparent komponentu",MB_ICONWARNING);
}
SetWindowPos(handle,HWND_TOP,0,0,0,0,SWP_NOMOVE | SWP_NOSIZE);
x = nleft;
y = ntop;
width = nwidth;
height = nheight;
Refresh();
}
简单的Combobox课程。
#pragma once
#include <Windows.h>
#include "Component.h"
#include "WinApiElement.h"
class Combobox : public Component
{
public:
Combobox(WinApiElement* Parent);
void AddItem(LPCSTR item);
};
现在出现问题:当我运行此代码时,Combobox没有显示。但是当我没有设置WndProc和UserData时,每个方面都可以,但它并不能让我满意。
@ edit
所以这是我的StaticWndProc功能代码
LRESULT CALLBACK WinApiElement::StaticWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
// Recover the pointer to our class, don't forget to type cast it back
WinApiElement* winptr = (WinApiElement*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
// Check if the pointer is NULL and call the Default WndProc
if (winptr == NULL)
{
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
else
{
// Call the Message Handler for my class (MsgProc in my case)
return winptr->InteriorWndProc(hwnd, uMsg, wParam, lParam);
}
}
在其中执行方法wndProc的InteriorWndproc。它看起来很奇怪,但InteriorWndProc支持标准Component的消息和方法WndProc对每个控件都不同。
LRESULT CALLBACK Component::InteriorWndProc(HWND hwnd,UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case WM_CREATE:
break;
case WM_SIZE:
OnResize();
break;
case WM_MOUSEMOVE:
POINT pt;
pt.x = GET_X_LPARAM(lParam);
pt.y = GET_Y_LPARAM(lParam);
OnMouseMove(pt.x,pt.y);
if(LButtonDown) OnLeftButtonHoldDown();
if(!mouseHover)
{
SetTimer(handle,TID_POLLMOUSE,MOUSE_POLL_DELAY,NULL);
OnMouseEnter();
mouseHover = true;
}
break;
case WM_TIMER:
if(mouseHover)
{
RECT rc;
GetWindowRect(handle,&rc);
GetCursorPos(&pt);
if(!PtInRect(&rc,pt))
{
KillTimer(handle,TID_POLLMOUSE);
OnMouseLeave();
mouseHover = false;
LButtonDown = false;
break;
}
}
break;
case WM_PAINT:
OnPaint();
break;
case WM_LBUTTONDOWN:
OnMouseLeftDown();
if(transparent)
{
((Component*)parent)->OnMouseLeftDown();
}
if(!LButtonDown)
{
OnLeftButtonHoldDown();
LButtonDown = true;
}
break;
case WM_LBUTTONUP:
LButtonDown = false;
break;
case WM_RBUTTONDOWN:
OnMouseRightDown();
break;
case WM_COMMAND:
break;
}
WndProc(hwnd,uMsg,wParam,lParam);
return DefWindowProc(hwnd,uMsg,wParam,lParam);
}