I'm trying to create a Label class where I can just reuse it later. What I've done is create a static control, then use the GDI+ library to DrawString on it.
It's almost done, I only have one issue where I need to automatically set the width and height of the static control to fit the text on it.
/** Call this function to redraw the content of static control **/ void ControlLabel::UpdateLabel() { if(LabelHandle != NULL) { SetWidthAndHeight(); SetWindowPos(LabelHandle, nullptr, xPosition, yPosition, width, height, SWP_NOZORDER | SWP_NOOWNERZORDER); InvalidateRect(LabelHandle, NULL, FALSE); UpdateWindow(LabelHandle); } } /** THis function is the callback of the 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 widestr; widestr = std::wstring(vFontFamily.begin(), vFontFamily.end()); FontFamily theFontFamily(widestr.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. widestr = std::wstring(text.begin(), text.end()); // convert text to std::wstring: g.DrawString(widestr.c_str(), -1, &font, pointF, &brush); // get the C string 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 specify, this is where the Label will be draw. Unique Label ID must be specify. **/ HWND ControlLabel::Label(int Label_ID, HWND WindowHandle) { SetWidthAndHeight(); LabelHandle = CreateWindowEx(0, L"STATIC", NULL, WS_CHILD | WS_VISIBLE | SS_OWNERDRAW, 0, 0, width, height, WindowHandle, NULL, NULL, NULL); //create the static control. SetWindowSubclass(LabelHandle, &LabelProc, LABEL_ID, 0); return LabelHandle; } I thought of using GetTextExtentPoint32 to calculate the height and width of the string, unfortunately, I failed to do so because of the font size and font family.
void ControlLabel::SetWidthAndHeight() { std::wstring stemp = StringConverter(vFontFamily); LPCWSTR result = stemp.c_str(); HDC hdc = GetDC(LabelHandle);//static control const wchar_t* buf = L"Hello World, this is 25 font size."; /*//(font test 1) HFONT hFont = CreateFont(vFontSize, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, result); */ //(font test 2) FontFamily theFontFamily(result); Font font(&theFontFamily, vFontSize, FontStyleRegular, UnitPixel); SIZE size; HFONT oldfont = (HFONT)SelectObject(hdc, &font); GetTextExtentPoint32(hdc, buf, wcslen(buf), &size); width = size.cx; height = size.cy; SelectObject(hdc, oldfont); DeleteObject(&font); ReleaseDC(LabelHandle, hdc); } How should I fix it?
UPDATE
Here's the complete source code of my class.
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 const wchar_t* buf = L"Hello World, this is 25 font size."; HFONT hFont = CreateFont( -MulDiv(vFontSize, GetDeviceCaps(hdc, LOGPIXELSX), 90), 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); DeleteObject(hFont); ReleaseDC(LabelHandle, hdc); 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 specify, this is where the Label will be draw. Unique Label ID must be specify. **/ HWND ControlLabel::Label(int Label_ID, HWND WindowHandle) { LABEL_ID = Label_ID; LabelHandle = CreateWindowEx(0, L"STATIC", NULL, WS_CHILD | WS_VISIBLE | SS_OWNERDRAW, 0, 0, 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.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; };
没有评论:
发表评论