C++;类的不同实例 我是C++新手,所以我不太确定这个问题的标题。无论如何,我创建了一个类,其目的是创建一个标签,然后在以后使用它一次又一次地创建另一个标签 CALLBACK MyClassName::WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) noexcept -> LRESULT { .... switch (msg) { .... case WM_CREATE: { ControlLabel controlLabel, anotherLabel; //declare two control label controlLabel.Label(123, hwnd); //Set new id and window handle for label controlLabel.SetXPosition(68); //Set x position controlLabel.SetYPosition(110); //Set y position controlLabel.SetText("This is Label"); //Set the text of Label controlLabel.SetFontSize(14); //Set the font size of the text anotherLabel.Label(456, hwnd); //Create and set new id and window handle for another label anotherLabel.SetXPosition(68); //Set x position of another label anotherLabel.SetYPosition(140); //Set y position of another label anotherLabel.SetText("This is another Label"); //Set the text of another label anotherLabel.SetFontSize(14); //Set the font size of another label break; } .... return ::DefWindowProcW(hwnd, msg, wparam, lparam); }
我希望它有两个不同标签的输出,例如 这是标签C++;类的不同实例 我是C++新手,所以我不太确定这个问题的标题。无论如何,我创建了一个类,其目的是创建一个标签,然后在以后使用它一次又一次地创建另一个标签 CALLBACK MyClassName::WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) noexcept -> LRESULT { .... switch (msg) { .... case WM_CREATE: { ControlLabel controlLabel, anotherLabel; //declare two control label controlLabel.Label(123, hwnd); //Set new id and window handle for label controlLabel.SetXPosition(68); //Set x position controlLabel.SetYPosition(110); //Set y position controlLabel.SetText("This is Label"); //Set the text of Label controlLabel.SetFontSize(14); //Set the font size of the text anotherLabel.Label(456, hwnd); //Create and set new id and window handle for another label anotherLabel.SetXPosition(68); //Set x position of another label anotherLabel.SetYPosition(140); //Set y position of another label anotherLabel.SetText("This is another Label"); //Set the text of another label anotherLabel.SetFontSize(14); //Set the font size of another label break; } .... return ::DefWindowProcW(hwnd, msg, wparam, lparam); },c++,winapi,visual-studio-2019,C++,Winapi,Visual Studio 2019,我希望它有两个不同标签的输出,例如 这是标签 这是另一个标签 相反,我得到了两个具有相同文本的标签 这是另一个标签 这是另一个标签 无论如何,这是这个类的完整来源 ControlLabel.H #pragma once #ifndef CONTROLLABEL_H #define CONTROLLABEL_H #include "Header.h" class ControlLabel { public: ControlLabel(); HWND Lab
这是另一个标签 相反,我得到了两个具有相同文本的标签 这是另一个标签
这是另一个标签 无论如何,这是这个类的完整来源 ControlLabel.H
#pragma once
#ifndef CONTROLLABEL_H
#define CONTROLLABEL_H
#include "Header.h"
class ControlLabel {
public:
ControlLabel();
HWND Label(int Label_ID, HWND WindowHandle);
void SetXPosition(int xPosition);
void SetYPosition(int yPosition);
void SetText(string Text);
void SetFontFamily(string FontFamily);
void SetFontSize(int FontSize);
void SetFontColor(int R, int G, int B);
void SetBackgroundColor(int Rr, int Gg, int Bb, bool SetBGColor);
private:
void UpdateLabel();
void SetWidthAndHeights();
static std::wstring StringConverter(const std::string& s);
static LRESULT CALLBACK LabelProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData);
static HWND LabelHandle;
static SolidBrush vFontColor;
static string text, vFontFamily;
static bool SetBGColor;
static int xPosition, yPosition, width, height, LABEL_ID, vFontSize, R, G, B, BckR, BckG, BckB;
};
#endif
ControlLabel.cpp
#include "ControlLabel.h"
HWND ControlLabel::LabelHandle = NULL;
int ControlLabel::xPosition = 0;
int ControlLabel::yPosition = 0;
int ControlLabel::width = 0;
int ControlLabel::height = 0;
int ControlLabel::LABEL_ID = 0;
int ControlLabel::vFontSize = 12;
int ControlLabel::R = 0;
int ControlLabel::G = 0;
int ControlLabel::B = 0;
int ControlLabel::BckR = 0;
int ControlLabel::BckG = 0;
int ControlLabel::BckB = 0;
bool ControlLabel::SetBGColor = FALSE;
string ControlLabel::text = "Label";
string ControlLabel::vFontFamily = "Segoe UI";
ControlLabel::ControlLabel() {}
/** This function is used to convert string into std::wstring. **/
std::wstring ControlLabel::StringConverter(const std::string& s) {
int len;
int slength = (int)s.length() + 1;
len = MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, 0, 0);
wchar_t* buf = new wchar_t[len];
MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, buf, len);
std::wstring r(buf);
delete[] buf;
return r;
}
/** This function is used to automatically set the Width and Height of static control base on the length of the text. **/
void ControlLabel::SetWidthAndHeights() {
std::wstring fontFamilyTemp = StringConverter(vFontFamily);
std::wstring textTemp = StringConverter(text);
LPCWSTR textLabel = textTemp.c_str();
HDC hdc = GetDC(LabelHandle);//static control
HFONT hFont = CreateFont(
-MulDiv(vFontSize, GetDeviceCaps(hdc, LOGPIXELSX), 90), //calculate the actual cHeight.
0, 0, 0, // normal orientation
FW_NORMAL, // normal weight--e.g., bold would be FW_BOLD
false, false, false, // not italic, underlined or strike out
DEFAULT_CHARSET, OUT_OUTLINE_PRECIS, // select only outline (not bitmap) fonts
CLIP_DEFAULT_PRECIS, CLEARTYPE_QUALITY, VARIABLE_PITCH | FF_SWISS, fontFamilyTemp.c_str());
SIZE size;
HFONT oldfont = (HFONT)SelectObject(hdc, hFont);
GetTextExtentPoint32(hdc, textLabel, wcslen(textLabel), &size);
width = size.cx;
height = size.cy;
SelectObject(hdc, oldfont); //don't forget to select the old.
DeleteObject(hFont); //always delete the object after creating it.
ReleaseDC(LabelHandle, hdc); //alway reelase dc after using.
/*char buffer[100];
sprintf_s(buffer, "WIDTH: %d | HEIGHT: %d\n", width, height);
OutputDebugStringA(buffer);*/
}
/** This function will be called when new option is set. For example, fontSize is set. **/
void ControlLabel::UpdateLabel() {
if(LabelHandle != NULL) {
SetWidthAndHeights();
SetWindowPos(LabelHandle, nullptr, xPosition, yPosition, width, height, SWP_NOZORDER | SWP_NOOWNERZORDER);
InvalidateRect(LabelHandle, NULL, FALSE);
UpdateWindow(LabelHandle);
}
}
/** This is the callback function of static control. **/
LRESULT CALLBACK ControlLabel::LabelProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData) {
switch(uMsg) {
case WM_ERASEBKGND: {
if(SetBGColor) { //We only want to do this if the SetColor is modified to true, meaning we want to set the color of background.
RECT rect;
GetClientRect(hwnd, &rect);
FillRect((HDC)wParam, &rect, CreateSolidBrush(RGB(BckR, BckG, BckB))); //set titlebar background color.
return 1; //return 1, meaning we take care of erasing the background.
}
return 0;
}case WM_PAINT: {
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
Graphics g(hdc);
std::wstring fontFamilyTemp = StringConverter(vFontFamily);
std::wstring textTemp = StringConverter(text);
FontFamily theFontFamily(fontFamilyTemp.c_str());
Font font(&theFontFamily, vFontSize, FontStyleRegular, UnitPixel);
SolidBrush brush(Color(255, R, G, B));
PointF pointF(0.0f, 0.0f);
TextRenderingHint hint = g.GetTextRenderingHint(); // Get the text rendering hint.
g.SetTextRenderingHint(TextRenderingHintAntiAlias); // Set the text rendering hint to TextRenderingHintAntiAlias.
g.DrawString(textTemp.c_str(), -1, &font, pointF, &brush);
EndPaint(hwnd, &ps);
return TRUE;
}case WM_NCDESTROY: {
RemoveWindowSubclass(hwnd, LabelProc, uIdSubclass);
return 0;
}
}
return DefSubclassProc(hwnd, uMsg, wParam, lParam);
}
/** Use this function to create a Label. Parent or WindowHandle must be specified, this is where the Label will be drawn. Unique Label ID must be specified. **/
HWND ControlLabel::Label(int Label_ID, HWND WindowHandle) {
LABEL_ID = Label_ID;
LabelHandle = CreateWindowEx(0, L"STATIC", NULL, WS_CHILD | WS_VISIBLE | SS_OWNERDRAW, xPosition, yPosition, width, height, WindowHandle, NULL, NULL, NULL); //create the static control.
SetWindowSubclass(LabelHandle, &LabelProc, LABEL_ID, 0);
return LabelHandle;
}
/** Use this function to set the X Position of the Label. **/
void ControlLabel::SetXPosition(int xxPosition) {
if(LabelHandle != NULL) {
xPosition = xxPosition; //set xposition
UpdateLabel();
}
}
/** Use this function to set the Y Position of the Label. **/
void ControlLabel::SetYPosition(int yyPosition) {
if(LabelHandle != NULL) {
yPosition = yyPosition; //set xposition
UpdateLabel();
}
}
/** Use this function to set the text of the Label. **/
void ControlLabel::SetText(string ttext) {
if(LabelHandle != NULL) {
text = ttext; //set text
UpdateLabel();
}
}
/** Use this function to set the font family of the Label. **/
void ControlLabel::SetFontFamily(string font_family) {
if(LabelHandle != NULL) {
vFontFamily = font_family; //set font family
UpdateLabel();
}
}
/** Use this function to set the font size of the Label. **/
void ControlLabel::SetFontSize(int size) {
if(LabelHandle != NULL) {
vFontSize = size; //set font size
UpdateLabel();
}
}
/** Use this Function to set the font color of the Label using RGB. **/
void ControlLabel::SetFontColor(int Rr, int Gg, int Bb) {
if(LabelHandle != NULL) {
R = Rr;
G = Gg;
B = Bb;
UpdateLabel();
}
}
/** Use this Function to set the background color of the Label using RGB. Last parameter must be TRUE if you want to set your own background color. **/
void ControlLabel::SetBackgroundColor(int Rr, int Gg, int Bb, bool setColor) {
if(LabelHandle != NULL) {
SetBGColor = setColor;
BckR = Rr;
BckG = Gg;
BckB = Bb;
UpdateLabel();
}
}
在类的所有实例之间共享。在您的类中有一个静态字符串文本
,因此所有实例都共享该文本。如果需要存储每个实例的数据,则需要使用非静态类成员
您可能已经使用了静态类成员,以便可以将窗口过程放在类的实现中(需要是静态的)。要使静态窗口过程访问每个实例数据,以前已经询问并回答过(如、或)。当所有变量都声明为静态时,没有“实例”这回事<代码>静态表示该变量在类的所有实例之间共享,使其基本上是全局的。所以,当你打电话时:
controlLabel.SetText("This is Label");
将文本指定给全局text
变量。然后,打电话
anotherLabel.SetText("This is another Label");
将新字符串指定给同一全局文本变量。此时您的原始字符串已被遗忘
你怎么解决这个问题?我可以想出很多办法,也许你可以想出更好的办法。其思想是以某种方式将文本(或整个controlLabel
实例)绑定到标签上
- 将标签文本直接放入窗口数据中(使用
WM_SETTEXT
。然后您可以在LabelProc
中将其向上拉并绘制,或者让默认的静态
窗口过程处理它
- 使标签为每个窗口实例保留了额外的空间,然后使用
StWindWindow 在整个C++代码中放置一个指针>控件标签>代码。在C++中,原始指针一般不是一个大的东西,但之后又为C创建了Win32 API,然后在需要时用代码< >将该实例拉上来。GetWindowLong
。只需记住取消静态
成员的文本
,这样它就不会被覆盖
使用全局/静态std::map
将每个标签与controlLabel
的实例相关联。同样,如果执行此操作,请记住取消static
文本
哦,当您调用任何以某种方式使用标签句柄的controlLabel
方法时,您恰好在LabelHandle
变量中随机获得了所需的句柄,因为它也是静态的没有任何意义,如果所有成员都是阿提克
但是,由于窗口过程的回调需要是静态的,因此您将无法访问该函数中的那些非静态成员
您可以使用子类的dwRefData
参数将类的实例传递到回调函数中。然后您可以强制转换该参数以访问非静态成员
例如,在::Label
函数中
SetWindowSubclass(LabelHandle, &LabelProc, LABEL_ID, <DWORD_PTR>(this)); //notice the last parameter, pass `this` instance so you can use `dwRefData`.
无论如何,我注意到您的类没有析构函数来销毁您的LabelHandle
。请确保这样做
ControlLabel.h //In your ControlLabel.h
~ControlLabel(); //should be in public
ControlLabel.cpp //In your ControlLabel.cpp
ControlLabel::~ControlLabel() {
if(LabelHandle) DestroyWindow(LabelHandle); //destroy when done.
}
ControlLabel controlLabel, anotherLabel; //declare two control label as Global.
CALLBACK MyClassName::WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) noexcept -> LRESULT {
....
switch (msg) {
....
case WM_CREATE:
{
controlLabel.Label(123, hwnd); //Set new id and window handle for label
...
anotherLabel.Label(456, hwnd); //Create and set new id and window handle for another label
...
break;
}
....
return ::DefWindowProcW(hwnd, msg, wparam, lparam);
}
ControlLabel.h //In your ControlLabel.h
~ControlLabel(); //should be in public
ControlLabel.cpp //In your ControlLabel.cpp
ControlLabel::~ControlLabel() {
if(LabelHandle) DestroyWindow(LabelHandle); //destroy when done.
}