gettextmetrics

本文详细介绍了GetTextMetrics函数的功能及使用方法。该函数能够获取指定字体的各种度量信息,并将其填充到指定的缓冲区中。文章解释了函数的参数含义、返回值以及可能遇到的错误情况。
  name="google_ads_frame" marginwidth="0" marginheight="0" src="http://pagead2.googlesyndication.com/pagead/ads?client=ca-pub-5572165936844014&dt=1193665761703&lmt=1193665780&format=336x280_as&output=html&correlator=1193665761687&url=http%3A%2F%2Fwww.codeguru.cn%2Fpublic%2Fiframe%2Fwinapiiframe.htm&color_bg=FFFFFF&color_text=000000&color_link=000000&color_url=FFFFFF&color_border=FFFFFF&ad_type=text&ga_vid=1285758818.1193665762&ga_sid=1193665762&ga_hid=111695597&flash=9&u_h=768&u_w=1024&u_ah=740&u_aw=1024&u_cd=32&u_tz=480&u_his=8&u_java=true" frameborder="0" width="336" scrolling="no" height="280" allowtransparency="allowtransparency">     函数功能:该函数给指定的缓冲区里填入当前选择字体的度量值。

    函数原型:BOOL GetTextMetrics(HDC hdc, LPTEXTMETRIC lptm);

    参数:

    hdc:设备环境句柄。

    lptm:指向结构TEXTMETRIC的指针,该结构用于接收度量值。

    返回值:如果函数调用成功,返回值非零,如果函数调用失败,返回值是0。

    Windows NT:若想获得更多错误信息,请调用GetLastError函数。

    备注:Windows CE环境下,对任何给定的字体,其度量值并不必需与Windows桌面平台下的正文度量值相匹配。

    速查:Windows NT:3.1及以上版本;Windows:95及以上版本;Windows CE:1.0及以上版本;头文件:wingdi.h;库文件:gdi32.lib;Unicode:在Windows NT环境下实现为Unicode和ANSI两种版本。

根据我提供的控件源码,写出一个更好的控件 #ifndef _CONSOLE_H_ #define _CONSOLE_H_ #define _CRT_SECURE_NO_WARNINGS #define NO_WARN_MBCS_MFC_DEPRECATION #include <SDKDDKVer.h> //#include <afxwin.h> #include <afxcmn.h> #include <concurrent_vector.h> #define CONSOLECOLOR_BLACK "\x1E\x1D" //字体 黑色 #define CONSOLECOLOR_RED "\x1E\x1F" //字体 红色 #define CONSOLECOLOR_GREEN "\x1E\x20" //字体 绿色 #define CONSOLECOLOR_YELLOW "\x1E\x21" //字体 黄色 #define CONSOLECOLOR_BLUE "\x1E\x22" //字体 蓝色 #define CONSOLECOLOR_PURPLE "\x1E\x23" //字体 紫色 #define CONSOLECOLOR_CYAN "\x1E\x24" //字体 青色 #define CONSOLECOLOR_DEF "\x1E\x25" //字体 默认色 class ScrollBar; struct LineInfo { DWORD m_dwStrLen;//行内容的长度 DWORD m_dwHead;//行首的sel游标 DWORD m_dwMaxSelWnd;//当前控件x轴尽头的sel DWORD m_dwTail;//行尾的sel int m_xPos;//行首的x开始坐标 int m_yPos;//行首的y开始坐标 DWORD m_dwMaxPixl;//此行内容占最大的像素 int* m_pDx; ~LineInfo() { if (m_pDx)delete[]m_pDx; } }; class Console: public CRichEditCtrl { public: Console(CWnd* _pParent); ~Console(); template<class ...Args> void Printf(const char* pformat, Args... args) { int len = std::snprintf(nullptr, 0, pformat, args...); if (len > 0) { char* szBuf = new char[len+1]; std::snprintf(szBuf, len+1, pformat, args...); split(szBuf); delete[]szBuf; } } private: void split(const char* _szText); void printf(const char* _szText); private: CDC* m_pDC; CRect m_rcWnd; BOOL m_bIsTrack; CFont m_Font;//默认字体,只是方便计算字体占屏幕长度使用的 int m_nFontSize;//默认字体大小(单位Twips) 如220Twip = 220/20 = 11磅 CHARFORMAT2 m_CF;//最终字体的数据 concurrency::concurrent_vector<LineInfo> m_vecLineInfo; ScrollBar* m_pHScroll; SCROLLINFO m_infoHScroll; DWORD m_pixCurMaxChars; ScrollBar* m_pVScroll; SCROLLINFO m_infoVScroll; int m_iLineHeight; int m_iStartPos_x; int m_iPrePos_x; bool m_bIsCapture; CHARRANGE m_StartSel; public: DECLARE_MESSAGE_MAP() afx_msg void OnEnSelchange(NMHDR* pNMHDR, LRESULT* pResult); afx_msg void OnEnMsgfilter(NMHDR* pNMHDR, LRESULT* pResult); afx_msg void OnMouseLeave(); afx_msg void OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar); }; extern Console* pConsole; #define console(_format, ...)pConsole->Printf(_format, ##__VA_ARGS__); #endif#include "Console.h" #include <io.h> #include <thread> #include "ScrollBar/ScrollBar.h" Console* pConsole = NULL; Console::Console(CWnd* _pParent) : m_nFontSize(10 * 10), m_bIsTrack(FALSE), m_pHScroll(NULL), m_pVScroll(NULL), m_pixCurMaxChars(0), m_iPrePos_x(0), m_iStartPos_x(0), m_bIsCapture(FALSE) { if (_pParent) { const char* szFontName = "lucida consoles"; //Arial _pParent->GetWindowRect(&m_rcWnd); m_rcWnd = {10, 0, m_rcWnd.Width()-15, m_rcWnd.Height()-15};//682 //| WS_HSCROLL | WS_VSCROLL if (CreateEx(NULL, WS_CHILD | WS_VISIBLE | ES_LEFT | ES_WANTRETURN | ES_MULTILINE | ES_READONLY | ES_AUTOHSCROLL | ES_AUTOVSCROLL, m_rcWnd, _pParent, 0))// { m_pDC = GetDC(); SetBackgroundColor(false, RGB(30, 30, 30));//设置背景颜色 LimitText(32767);//系统默认设置是 32767 = 31.999kb 只能限制用户的输入 //创建新字体数据,此字体只是方便计算屏幕显示的长度用的。最终字体数据以 CHARFORMAT2 为准 //以十分之一磅为单位。例如,如果你想要一个12磅的字体,你应该传递120作为这个参数。 m_Font.CreatePointFont(m_nFontSize, szFontName);// 100/10 =10磅,相当于200Twip CreatePointFont用的单位是Point, 是磅的10倍,刚好是Twips的一半 SetFont(&m_Font);//设置字体 m_pDC->SelectObject(&m_Font);//dc选择当前字体 /* 1缇等于1/1440 英寸或1/567厘米 缇(Twips) (缇:计量单位,等于“磅”的 1/20,英寸的 1/1440。一厘米有 567 缇。 像素(Pixels):监视器或打印机分辨率的最小单位 右键单击桌面,选择属性,选择“设置”选卡,单击高级按钮。 里面出现DPI设置。一般为“正常尺寸(96 DPI)”。 DPI的意思就是 DPI(Dots per Inch)。因此我们可以得到如下换算公式 1 Pixel = 1440 TPI / 96 DPI = 15 Twips 1 Twip = 96 DPI / 1440 TPI = 0.0666667 Pixels 磅:指打印的字符的高度的度量单位, 1磅等于1/72英寸,或大约等于1厘米的 1/28。 英寸:2.54 厘米 一般情况下:1厘米=8505像素 20Twip = 1磅 = 20*0.0666667 = 1.333334 Pixels */ LRESULT FontStyle = 0; FontStyle = SendMessage(EM_GETLANGOPTIONS, 0, 0); if (FontStyle & IMF_DUALFONT) { FontStyle &= ~IMF_DUALFONT; //"<CRichEdit_Ctrl::CRichEdit_Ctrl>成功去掉IMF_DUALFONT"; } SendMessage(EM_SETLANGOPTIONS, 0, (LPARAM)FontStyle); /* PARAFORMAT2 pf; ZeroMemory(&pf, sizeof(PARAFORMAT2)); pf.cbSize = sizeof pf; pf.dwMask |= PFM_ALL; pf.bLineSpacingRule = 100; pf.dyLineSpacing = 400; pf.dySpaceAfter = 400; pf.dySpaceBefore = 400; pf.dxStartIndent = 100; pf.dxRightIndent = 100; SetParaFormat(pf); */ TEXTMETRIC tm; ::GetTextMetrics(m_pDC->GetSafeHdc(), &tm); m_iLineHeight = tm.tmHeight + (tm.tmDescent*2);//取得行高 //准确的字体数据 memset(&m_CF, 0, sizeof(m_CF)); //StrCpyA(m_CF.szFaceName, szFontName);//设置字体 //m_CF.cbSize = sizeof(CHARFORMAT2); m_CF.dwMask = CFM_EFFECTS | CFM_COLOR; m_CF.dwEffects = 0; m_CF.crTextColor = RGB(165, 165, 165);//设置颜色 //m_CF.yHeight = m_nFontSize;//除20得到磅 如 200/20 = 10磅 //默认的字符磅数 SetDefaultCharFormat(m_CF);//设置字体 SetEventMask(GetEventMask() | ENM_CHANGE | ENM_SELCHANGE | ENM_SCROLL | ENM_MOUSEEVENTS); //创建滚动动 m_pHScroll = new ScrollBar(); if (m_pHScroll->Create(SB_HORZ, CRect(m_rcWnd.left, m_rcWnd.Height(), m_rcWnd.right, m_rcWnd.Height()+15), _pParent)) { m_pHScroll->SetTarget(this); memset(&m_infoHScroll, 0, sizeof m_infoHScroll); m_infoHScroll.cbSize = sizeof m_infoHScroll; m_infoHScroll.fMask = SIF_ALL; m_infoHScroll.nPage = m_rcWnd.Width(); } m_pVScroll = new ScrollBar(); if (m_pVScroll->Create(SB_VERT, CRect(m_rcWnd.right, m_rcWnd.top, m_rcWnd.right+15, m_rcWnd.bottom), _pParent)) { m_pVScroll->SetTarget(this); memset(&m_infoVScroll, 0, sizeof m_infoVScroll); m_infoVScroll.cbSize = sizeof m_infoVScroll; m_infoVScroll.fMask = SIF_ALL; m_infoVScroll.nPage = m_rcWnd.Height(); } } } } Console::~Console() { m_Font.DeleteObject(); if (m_pHScroll)delete m_pHScroll; if (m_pVScroll)delete m_pVScroll; for (concurrency::concurrent_vector<LineInfo>::iterator iter = m_vecLineInfo.begin(); iter != m_vecLineInfo.end(); iter++) { if (iter->m_pDx) { delete[] iter->m_pDx; iter->m_pDx = NULL; } } } /* *0x1E RS (Record Separator) 记录分离符 属性代码 颜色 29 黑色 = 0x1D 31 红色 = 0x1F 32 绿色 = 0x20 33 黄色 = 0x21 34 蓝色 = 0x22 35 紫色 = 0x23 36 青色 = 0x24 */ void Console::printf(const char* _szText) { const char* szText = _szText; char byteColor = 0; //如果\n会替换成\r int indexLine = LineFromChar(-1);//取出当前行号 long lStart = 0; long lEnd = 0; GetSel(lStart, lEnd);//取得当前的光标位置 CString szStart; GetTextRange(lStart - 1, lEnd, szStart);//当前光标向后选择一位字符,并取出此字符 if (szStart == '\r' || szStart == "")//判断字符是否行头 { CPoint point = PosFromChar(lEnd); LineInfo info; memset(&info, 0, sizeof info); info.m_dwHead = lEnd; info.m_xPos = point.x; info.m_yPos = point.y; m_vecLineInfo.push_back(info);//保存行头的光标位置 } if (_szText[0] == '\x1E') { switch (_szText[1]) { case '\x1D': { m_CF.crTextColor = RGB(0, 0, 0); break; } case '\x1F': { m_CF.crTextColor = RGB(255, 0, 0); break; } case '\x20': { m_CF.crTextColor = RGB(0, 255, 0); break; } case '\x21': { m_CF.crTextColor = RGB(255, 255, 0); break; } case '\x22': { m_CF.crTextColor = RGB(0, 0, 255); break; } case '\x23': { m_CF.crTextColor = RGB(199, 0, 106); break; } case '\x24': { m_CF.crTextColor = RGB(0, 255, 255); break; } default: { m_CF.crTextColor = RGB(165, 165, 165); break; } } szText = _szText+2; SetSelectionCharFormat(m_CF); } ReplaceSel(szText); m_CF.crTextColor = RGB(165, 165, 165);//重置回原始颜色 SetSelectionCharFormat(m_CF); LineInfo* pInfo = &(m_vecLineInfo[indexLine]); //尝试取出控件尽头x轴末尾是否有字符存在 GetSel(lStart, lEnd);//取得当前的光标位置 GetTextRange(lEnd - 1, lEnd, szStart);//当前光标向后选择一位字符,并取出此字符 bool bIsEnter = false; if (szStart == '\r') { //已经完成换行操作 bIsEnter = true; pInfo->m_dwTail = lEnd - 1; GetTextRange(pInfo->m_dwHead, pInfo->m_dwTail, szStart);//取出本行内容 CPoint point = PosFromChar(pInfo->m_dwTail); pInfo->m_dwMaxPixl = point.x-1;//此行文本的最大像素 int len = szStart.GetLength(); int iFit = 0; CSize size = { 0, 0 }; if (pInfo->m_pDx) { delete [] pInfo->m_pDx; pInfo->m_pDx = NULL; } pInfo->m_pDx = new int[len]; pInfo->m_dwStrLen = len; ::GetTextExtentExPoint(m_pDC->GetSafeHdc(), szStart, len, point.x, &iFit, pInfo->m_pDx, &size);//计算出本行每个字符所占的像素,并把每个字符的像素存在m_pDx数组里面 pInfo->m_yPos = indexLine * m_iLineHeight; } else { pInfo->m_dwTail = lEnd; CPoint point = PosFromChar(pInfo->m_dwTail); pInfo->m_dwMaxPixl = point.x;//此行文本的最大像素 } //重置水平滚动条信息 if (pInfo->m_dwMaxPixl > (DWORD)m_rcWnd.Width() && pInfo->m_dwMaxPixl > m_pixCurMaxChars) { m_pixCurMaxChars = pInfo->m_dwMaxPixl; m_infoHScroll.nMax = m_pixCurMaxChars; m_pHScroll->SetScrollInfo(m_infoHScroll); } if (bIsEnter) { //已经完成换行操作 if (((indexLine + 1) * m_iLineHeight) > m_rcWnd.Height()) { m_infoVScroll.nMax = ((indexLine + 1) * m_iLineHeight); m_pVScroll->SetScrollInfo(m_infoVScroll); m_pVScroll->SetScrollPos(m_infoVScroll.nMax - m_rcWnd.Height());//向下滚动 } LineScroll(1); } } void Console::split(const char* _szText) { const char* szCurText = _szText; const char* szOldText = _szText; char* szPreText = NULL; int len = NULL; const char* szClrText = NULL; if (_szText[0] != '\x1E') { bool bIsFined = false; while ((szClrText = strchr(szCurText, '\x1E'))) { bIsFined = true; len = szClrText - szOldText; szPreText = new char[len + 1]; szPreText[len] = 0; memcpy(szPreText, szOldText, len); Console::printf(szPreText); delete[]szPreText; szCurText = szClrText + 1; szOldText = szClrText; } if (bIsFined) { if(szOldText)Console::printf(szOldText); } else { Console::printf(_szText); } } else { bool bIsFined = false; szCurText = _szText + 1; while ((szClrText = strchr(szCurText, '\x1E'))) { bIsFined = true; len = szClrText - szOldText; szPreText = new char[len + 1]; szPreText[len] = 0; memcpy(szPreText, szOldText, len); Console::printf(szPreText); delete[]szPreText; szCurText = szClrText + 1; szOldText = szClrText; } if (szOldText) { Console::printf(szOldText); } } } BEGIN_MESSAGE_MAP(Console, CRichEditCtrl) ON_NOTIFY_REFLECT(EN_SELCHANGE, &Console::OnEnSelchange) ON_NOTIFY_REFLECT(EN_MSGFILTER, &Console::OnEnMsgfilter) ON_WM_MOUSELEAVE() ON_WM_VSCROLL() END_MESSAGE_MAP() void Console::OnEnSelchange(NMHDR* pNMHDR, LRESULT* pResult) { SELCHANGE* pSelChange = reinterpret_cast<SELCHANGE*>(pNMHDR); // TODO: 控件将不发送此通知,除非您重写 // CRichEditCtrl::OnInitDialog() 函数,以将 EM_SETEVENTMASK 消息发送 // 到该控件,同时将 ENM_SELCHANGE 标志“或”运算到 lParam 掩码中。 // TODO: 在此添加控件通知处理程序代码 int iLineIndex = -1; iLineIndex = LineFromChar(pSelChange->chrg.cpMax); if (iLineIndex != -1 && iLineIndex < (int)m_vecLineInfo.size()) { CHARRANGE LineStartSel; LineInfo* pInfo = &m_vecLineInfo[iLineIndex]; switch (pSelChange->seltyp) { case 0://鼠标点击在某处文本的某个sel中 { //开始存储此行的选择sel起始位置 m_StartSel = pSelChange->chrg; break; } case CBN_EDITCHANGE://鼠标左键按住拖动选择文本 { //通过m_StartSel算出本行的选择起始位置 CPoint point = PosFromChar(m_StartSel.cpMin);//算出sel处于控件内坐标 int x = point.x; point.y = pInfo->m_yPos;//替换上本行的y坐标 LineStartSel.cpMin = CharFromPos(point);//算出本行起始位置 LineStartSel.cpMax = LineStartSel.cpMin; point = PosFromChar(LineStartSel.cpMin); if (point.x < x - 5) { //outputdebug_default("行号:%d 检测到起始位置异常,和原位差太远", iLineIndex); LineStartSel.cpMin = 0; LineStartSel.cpMax = 0; if (point.x > m_rcWnd.Width()) { m_pHScroll->SetScrollPos(point.x - m_rcWnd.Width());//通知滚动条 } else { m_pHScroll->SetScrollPos(0); } } if (pSelChange->chrg.cpMax > LineStartSel.cpMax) { //outputdebug_default("行号:%d 从左向右选择文本: %d", iLineIndex, pSelChange->chrg.cpMax); CString str; GetTextRange(pInfo->m_dwHead, pSelChange->chrg.cpMax, str); int len = str.GetLength(); if (--len > -1 && len < (int)pInfo->m_dwStrLen) { //outputdebug_default("行号:%d, 当前光标所占像素: %d", iLineIndex, pInfo->m_pDx[len]); int pix = pInfo->m_pDx[len]; if (pix > m_rcWnd.Width()) { //outputdebug_default("行号:%d, 当前光标所占像素超出控件长度: %d", iLineIndex, pix); m_pHScroll->SetScrollPos(pix - m_rcWnd.Width());//通知滚动条 } } else { if (--len > -1 && pInfo->m_dwStrLen == 0) { //此行末尾没有/r回车符 CPoint point = PosFromChar(pSelChange->chrg.cpMax); if (point.x > m_rcWnd.Width()) { m_pHScroll->SetScrollPos(point.x - m_rcWnd.Width());//通知滚动条 } else { m_pHScroll->SetScrollPos(0); } } else { int i = 0; } } } else if (pSelChange->chrg.cpMax != pInfo->m_dwHead) { //outputdebug_default("行号:%d 从右向左选择文本: head:%d start:%d, min:%d max:%d", iLineIndex, pInfo->m_dwHead, LineStartSel.cpMax, pSelChange->chrg.cpMin, pSelChange->chrg.cpMax); if (pSelChange->chrg.cpMin == pInfo->m_dwHead) { m_pHScroll->SetScrollPos(0); } } else { //outputdebug_default("x行号:%d 从右向左选择文本: head:%d start:%d, min:%d max:%d", iLineIndex, pInfo->m_dwHead, LineStartSel.cpMax, pSelChange->chrg.cpMin, pSelChange->chrg.cpMax); if (pInfo->m_dwHead == pSelChange->chrg.cpMax)//本行头部和上一行行尾重复,定位回上一行 { if (--iLineIndex > -1) { pInfo = &m_vecLineInfo[iLineIndex]; CString str; GetTextRange(pInfo->m_dwHead, pSelChange->chrg.cpMax, str); int len = str.GetLength(); //outputdebug_default("行号:%d, 当前光标所占像素: %d len:%d", iLineIndex, pInfo->m_pDx[len-2], len); if (--len > -1 && len <= (int)pInfo->m_dwStrLen) { int pix = pInfo->m_pDx[len-1]; if (pix > m_rcWnd.Width()) { //outputdebug_default("行号:%d, 当前光标所占像素超出控件长度: %d", iLineIndex, pix); //m_pHScroll->SetScrollPos(pix - m_rcWnd.Width());//通知滚动条 } } } } } break; } } } //outputdebug_default("min:%d max:%d", pSelChange->chrg.cpMin, pSelChange->chrg.cpMax); *pResult = 0; } void Console::OnEnMsgfilter(NMHDR* pNMHDR, LRESULT* pResult) { MSGFILTER* pMsgFilter = reinterpret_cast<MSGFILTER*>(pNMHDR); // TODO: 控件将不发送此通知,除非您重写 // CRichEditCtrl::OnInitDialog() 函数,以将 EM_SETEVENTMASK 消息发送 // 到该控件,同时将 ENM_KEYEVENTS 或 ENM_MOUSEEVENTS 标志 //“或”运算到 lParam 掩码中。 // TODO: 在此添加控件通知处理程序代码 switch(pMsgFilter->msg) { case WM_MOUSEMOVE: { /* if (pMsgFilter->wParam == MK_LBUTTON) { int xPos = GET_X_LPARAM(pMsgFilter->lParam); int yPos = GET_Y_LPARAM(pMsgFilter->lParam); //outputdebug_default("x: %d, y:%d",xPos, yPos); if (m_bIsCapture) { if (xPos > m_iStartPos_x) { //outputdebug_default("正在从左向右选择文本."); } else { //outputdebug_default("正在从右向左选择文本."); } m_iPrePos_x = xPos; } }*/ if (!m_bIsTrack) { m_bIsTrack = TRUE; TRACKMOUSEEVENT tme; tme.cbSize = sizeof(tme); tme.hwndTrack = m_hWnd; tme.dwFlags = TME_LEAVE | TME_HOVER; tme.dwHoverTime = 1;// 鼠标在按钮上停留超过 1ms ,才认为成功 _TrackMouseEvent(&tme); } break; } case WM_LBUTTONDOWN: { if (pMsgFilter->wParam == MK_LBUTTON) { int xPos = GET_X_LPARAM(pMsgFilter->lParam); int yPos = GET_Y_LPARAM(pMsgFilter->lParam); m_iPrePos_x = xPos; m_iStartPos_x = xPos; m_bIsCapture = TRUE; //outputdebug_default("x: %d, y:%d", xPos, yPos); } break; } case WM_LBUTTONUP: { if (pMsgFilter->wParam == MK_LBUTTON) { m_bIsCapture = FALSE; } break; } } *pResult = 0; } void Console::OnMouseLeave() { // TODO: 在此添加消息处理程序代码和/或调用默认值 m_bIsTrack = FALSE; ::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW)); CRichEditCtrl::OnMouseLeave(); } void Console::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) { // TODO: 在此添加消息处理程序代码和/或调用默认值 CRichEditCtrl::OnVScroll(nSBCode, nPos, pScrollBar); }
07-02
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { HDC hdc; HFONT hF_black, hF_big; PAINTSTRUCT ps; TEXTMETRIC tm; int X = 0, Y = 0; RECT rect; SIZE size; LPCWSTR lpsz_1 = L"这是一行红色的、字体为SYSTEM_FONT的字体,红色代表未来。"; LPCWSTR lpsz_2 = L"现在显示的是自定义字体,颜色为绿色,绿色代表生机勃勃。"; LPCWSTR lpsz_3 = L"现在展现在您面前的是蓝色的粗体字,蓝色代表广阔的海洋和天空。"; LPCWSTR lpsz_4 = L"当前字体为大号、斜体并带有下划线的文字。"; LPCWSTR lpsz_5 = L"现在您掌握了字体的操作了吗?祝您成功!"; switch (message) { case WM_CREATE: { SetTimer(hwnd, 9999, 50, NULL); break; } case WM_TIMER: { if (wParam == 9999) { InvalidateRect(hwnd, NULL, true); } break; } case WM_PAINT: { rect.right += 2; hdc = BeginPaint(hwnd, &ps); SetTextColor(hdc, RGB(255, 0, 0)); GetTextMetrics(hdc, &tm); TextOut(hdc, X, Y, lpsz_1, _tcsclen(lpsz_1)); Y = Y + tm.tmHeight + tm.tmExternalLeading; hF_black = CreateFont ( 20, 0, 0, 0, FW_HEAVY, 0, 0, 0, GB2312_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH|FF_DONTCARE, L"粗体字" ); SetTextColor(hdc, RGB(0, 255, 0)); SelectObject(hdc, hF_black); GetTextMetrics(hdc, &tm); TextOut(hdc, X, Y, lpsz_2, _tcsclen(lpsz_2)); Y = Y + tm.tmHeight + tm.tmExternalLeading; GetTextExtentPoint32(hdc, lpsz_2, _tcsclen(lpsz_2), &size); EndPaint(hwnd, &ps); return 0; } case WM_DESTROY: PostQuitMessage(0); return 0; default: return DefWindowProc(hwnd, message, wParam, lParam); } } 严重性 代码 说明 项目 文件 行 禁止显示状态 详细信息 错误(活动) E0167 "LPCWSTR" (aka "const WCHAR *") 类型的实参与 "LPCSTR" (aka "const CHAR *") 类型的形参不兼容 1 D:\桌面\win第5周作业\1\1.cpp 93 严重性 代码 说明 项目 文件 行 禁止显示状态 详细信息 错误(活动) E0167 "LPCWSTR" (aka "const WCHAR *") 类型的实参与 "const char *" 类型的形参不兼容 1 D:\桌面\win第5周作业\1\1.cpp 93 严重性 代码 说明 项目 文件 行 禁止显示状态 详细信息 错误(活动) E0167 "const wchar_t *" 类型的实参与 "LPCSTR" (aka "const CHAR *") 类型的形参不兼容 1 D:\桌面\win第5周作业\1\1.cpp 112
03-19
#include <Windows.h> #include <iostream> #include <tchar.h> LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); struct METRICS { const TCHAR* m_pLabel; const TCHAR* m_pDesc; int m_nIndex; }; void PrintTextMetrics(HDC hdc) { // 定义 TEXTMETRIC 结构体变量 TEXTMETRIC tm; // 调用 GetTextMetrics 填充 tm 结构体 if (GetTextMetrics(hdc, &tm)) { // 输出字体度量信息 std::cout << "tmHeight: " << tm.tmHeight << std::endl; std::cout << "Ascent: " << tm.tmAscent << std::endl; std::cout << "Descent: " << tm.tmDescent << std::endl; std::cout << "Internal Leading: " << tm.tmInternalLeading << std::endl; std::cout << "External Leading: " << tm.tmExternalLeading << std::endl; std::cout << "Average Char Width: " << tm.tmAveCharWidth << std::endl; std::cout << "Max Char Width: " << tm.tmMaxCharWidth << std::endl; std::cout << "Weight: " << tm.tmWeight << std::endl; // 可以继续添加其他感兴趣的成员... } else { std::cerr << "Failed to get text metrics." << std::endl; } } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { // 分配控制台 AllocConsole(); // 将标准输出重定向到控制台 FILE* stream; freopen_s(&stream, "CONOUT$", "w", stdout); TCHAR ClassName[] = TEXT("滚动条"); WNDCLASS window = {}; window.lpfnWndProc = WindowProc; window.hInstance = hInstance; window.lpszClassName = ClassName; window.hCursor = LoadCursor(NULL, IDC_ARROW);//该设置决定了鼠标在窗口客户区显示的光标样式 RegisterClass(&window); HWND hwnd = CreateWindowEx( 0, ClassName, TEXT("滚动条示例"), WS_OVERLAPPEDWINDOW | WS_VSCROLL | WS_HSCROLL, CW_USEDEFAULT, CW_USEDEFAULT, 800, 600, NULL, NULL, hInstance, NULL ); if (!hwnd) return 0; ShowWindow(hwnd, nCmdShow); MSG msg = {}; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return 0; } LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { HDC hdc; PAINTSTRUCT ps; TEXTMETRIC tm; SCROLLINFO si; HFONT hFont, hFontOld; static int s_iCol1 = 0, s_iCol2 = 0, s_iCol3 = 0, s_iHeight = 0; static int s_cxClient, s_cyClient; static int s_cxChar; int iVertPos, iHorzPos; SIZE size = { 0 }; int x, y; TCHAR szBuf[10]; METRICS metrics[] = { {TEXT("Label1"), TEXT("Description1"), SM_CXSCREEN}, {TEXT("Label2"), TEXT("Description2"), SM_CYSCREEN}, {TEXT("Label3"), TEXT("Description3"), SM_CXFULLSCREEN} }; const int NUMLINES = sizeof(metrics) / sizeof(METRICS); // 假设有3行数据 switch (uMsg) { case WM_CREATE: hdc = GetDC(hwnd); hFont = CreateFont(32, 0, 0, 0, 0, 0, 0, 0, GB2312_CHARSET, 0, 0, 0, 0, TEXT("宋体")); hFontOld = (HFONT)SelectObject(hdc, hFont); for (int i = 0; i < NUMLINES; i++) { GetTextExtentPoint32(hdc, metrics[i].m_pLabel, _tcslen(metrics[i].m_pLabel), &size); if (size.cx > s_iCol1) s_iCol1 = size.cx; GetTextExtentPoint32(hdc, metrics[i].m_pDesc, _tcslen(metrics[i].m_pDesc), &size); if (size.cx > s_iCol2) s_iCol2 = size.cx; GetTextExtentPoint32(hdc, szBuf, _stprintf_s(szBuf, _countof(szBuf), TEXT("%d"), GetSystemMetrics(metrics[i].m_nIndex)), &size); if (size.cx > s_iCol3) s_iCol3 = size.cx; } s_iHeight = size.cy + 2; GetTextMetrics(hdc, &tm); s_cxChar = tm.tmAveCharWidth; SelectObject(hdc, hFontOld); DeleteObject(hFont); ReleaseDC(hwnd, hdc); return 0; case WM_SIZE: s_cxClient = LOWORD(lParam); s_cyClient = HIWORD(lParam); si.cbSize = sizeof(SCROLLINFO); si.fMask = SIF_RANGE | SIF_PAGE; si.nMin = 0; si.nMax = 200; //si.nMax = NUMLINES - 1; si.nPage = s_cyClient / s_iHeight; SetScrollInfo(hwnd, SB_VERT, &si, TRUE); si.cbSize = sizeof(SCROLLINFO); si.fMask = SIF_RANGE | SIF_PAGE; si.nMin = 0; si.nMax = 200; //si.nMax = (s_iCol1 + s_iCol2 + s_iCol3) / s_cxChar - 1; si.nPage = s_cxClient / s_cxChar; SetScrollInfo(hwnd, SB_HORZ, &si, TRUE); return 0; case WM_VSCROLL: si.cbSize = sizeof(SCROLLINFO); si.fMask = SIF_ALL; GetScrollInfo(hwnd, SB_VERT, &si); iVertPos = si.nPos; switch (LOWORD(wParam)) { case SB_LINEUP: si.nPos -= 1; break; case SB_LINEDOWN: si.nPos += 1; break; case SB_PAGEUP: //si.nPos -= si.nPage; si.nPos -= 10; break; case SB_PAGEDOWN: //si.nPos += si.nPage; si.nPos += 10; break; case SB_THUMBTRACK: si.nPos = si.nTrackPos; break; } // 设置位置,然后获取位置,如果 si.nPos 越界,Windows 不会设置 si.cbSize = sizeof(SCROLLINFO); si.fMask = SIF_POS; SetScrollInfo(hwnd, SB_VERT, &si, TRUE); GetScrollInfo(hwnd, SB_VERT, &si); // 如果 Windows 更新了滚动条位置,我们更新客户区 if (iVertPos != si.nPos) InvalidateRect(hwnd, NULL, TRUE); return 0; case WM_HSCROLL: si.cbSize = sizeof(SCROLLINFO); si.fMask = SIF_ALL; GetScrollInfo(hwnd, SB_HORZ, &si); iHorzPos = si.nPos; switch (LOWORD(wParam)) { case SB_LINEUP: si.nPos -= 1; break; case SB_LINEDOWN: si.nPos += 1; break; case SB_PAGEUP: //si.nPos -= si.nPage; si.nPos -= 10; break; case SB_PAGEDOWN: //si.nPos += si.nPage; si.nPos += 10; break; case SB_THUMBTRACK: si.nPos = si.nTrackPos; break; } // 设置位置,然后获取位置,如果 si.nPos 越界,Windows 不会设置 si.cbSize = sizeof(SCROLLINFO); si.fMask = SIF_POS; SetScrollInfo(hwnd, SB_HORZ, &si, TRUE); GetScrollInfo(hwnd, SB_HORZ, &si); // 如果 Windows 更新了滚动条位置,我们更新客户区 if (iHorzPos != si.nPos) InvalidateRect(hwnd, NULL, TRUE); return 0; case WM_PAINT: hdc = BeginPaint(hwnd, &ps); // 获取垂直滚动条、水平滚动条位置 si.cbSize = sizeof(SCROLLINFO); si.fMask = SIF_POS; GetScrollInfo(hwnd, SB_VERT, &si); iVertPos = si.nPos; //si.cbSize = sizeof(SCROLLINFO); //si.fMask = SIF_POS; GetScrollInfo(hwnd, SB_HORZ, &si); iHorzPos = si.nPos; SetBkMode(hdc, TRANSPARENT); hFont = CreateFont(32, 0, 0, 0, 0, 0, 0, 0, GB2312_CHARSET, 0, 0, 0, 0, TEXT("宋体")); hFontOld = (HFONT)SelectObject(hdc, hFont); for (int i = 0; i < NUMLINES; i++) { x = s_cxChar * (-iHorzPos); y = s_iHeight * (i - iVertPos); // 先格式化字符串 int len = _stprintf_s(szBuf, _countof(szBuf), TEXT("%d"), GetSystemMetrics(metrics[i].m_nIndex)); TextOut(hdc, x, y, metrics[i].m_pLabel, _tcslen(metrics[i].m_pLabel)); TextOut(hdc, x + s_iCol1, y, metrics[i].m_pDesc, _tcslen(metrics[i].m_pDesc)); TextOut(hdc, x + s_iCol1 + s_iCol2, y, szBuf, len); // 使用 len } SelectObject(hdc, hFontOld); DeleteObject(hFont); EndPaint(hwnd, &ps); return 0; case WM_DESTROY: PostQuitMessage(0); return 0; default: return DefWindowProc(hwnd, uMsg, wParam, lParam); } } 滚动条移动时重影
最新发布
08-03
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值