MFC: 控件根據文本內容大小自動調整

背景:

針對不同語言下,控件顯示不全的現象;
例如:
現象1:中文下顯示全部信息,英語下只能顯示部分文字
現象2:中文下顯示不全## 實現思路:

  1. 控件綁定按鈕
  2. 計算控件文本長度
  3. 根據文本長度顯示控件位置

舉例:

Buttion按鈕:
在這里插入圖片描述

  1. 控件綁定按鈕
BEGIN_MESSAGE_MAP(CTestDlg, CDialogEx)ON_WM_SYSCOMMAND()ON_WM_PAINT()ON_WM_QUERYDRAGICON()ON_BN_CLICKED(IDC_BUTTON1, &CTestDlg::OnBnClickedButton1)
END_MESSAGE_MAP()
private:CButton m_btnOpenFile;
  1. 計算控件文本長度
// 修正后的計算函數
int CalBtnTextWidth(CButton &btn) 
{CClientDC dc(&btn); // 使用CClientDC替代CPaintDCCFont* pFont = btn.GetFont();dc.SelectObject(pFont);CString strText;btn.GetWindowText(strText);CRect rectText(0,0,0,0);dc.DrawText(strText, &rectText, DT_CALCRECT | DT_SINGLELINE); // 修正拼寫return rectText.Width() + 8; // 增加文本邊距
}
  1. 根據文本長度顯示控件位置
WINDOWPLACEMENT sBtnOpenFile;
GetDlgItem(IDB_OPENFILE)->GetWindowPlacement(&sBtnOpenFile);
int nBtnTextWidth = CalBtnTextWidth(m_btnOpenFile);
// 計算按鈕的初始寬度
int initWidth = sBtnOpenFile.rcNormalPosition.right - sBtnOpenFile.rcNormalPosition.left;
// 選擇新寬度(取最大值)
int newWidth = max(initWidth, textWidth);
sBtnOpenFile.rcNormalPosition.left = sBtnOpenFile.rcNormalPosition.Right - newWidth;
GetDlgItem(IDB_OPENFILE)->SetWindowPlacement(&sBtnOpenFile);

完整代碼模塊:


// TestDlg.h : 頭文件
//#pragma once
#include "afxwin.h"// CTestDlg 對話框
class CTestDlg : public CDialogEx
{
// 構造
public:CTestDlg(CWnd* pParent = NULL);	// 標準構造函數// 對話框數據
#ifdef AFX_DESIGN_TIMEenum { IDD = IDD_TEST_DIALOG };
#endifprotected:virtual void DoDataExchange(CDataExchange* pDX);	// DDX/DDV 支持// 實現
protected:HICON m_hIcon;// 生成的消息映射函數virtual BOOL OnInitDialog();afx_msg void OnSysCommand(UINT nID, LPARAM lParam);afx_msg void OnPaint();afx_msg HCURSOR OnQueryDragIcon();DECLARE_MESSAGE_MAP()
private:CButton m_btnOpenFile;private:int CalBtnTextWidth(CButton &btn);void AdjustButtonSize(CButton &btn);CComboBox TEST;
};

// TestDlg.cpp : 實現文件
//#include "stdafx.h"
#include "Test.h"
#include "TestDlg.h"
#include "afxdialogex.h"
#include <afxwin.h>  // MFC 核心頭文件
#include <windows.h>  // Windows API 頭文件(包含 WINDOWPLACEMENT)
#include <algorithm>  // 使用 std::max#ifdef _DEBUG
#define new DEBUG_NEW
#endif// 用于應用程序“關于”菜單項的 CAboutDlg 對話框class CAboutDlg : public CDialogEx
{
public:CAboutDlg();// 對話框數據
#ifdef AFX_DESIGN_TIMEenum { IDD = IDD_ABOUTBOX };
#endifprotected:virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持// 實現
protected:DECLARE_MESSAGE_MAP()
};CAboutDlg::CAboutDlg() : CDialogEx(IDD_ABOUTBOX)
{
}void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{CDialogEx::DoDataExchange(pDX);
}BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
END_MESSAGE_MAP()// CTestDlg 對話框CTestDlg::CTestDlg(CWnd* pParent /*=NULL*/): CDialogEx(IDD_TEST_DIALOG, pParent)
{m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}void CTestDlg::DoDataExchange(CDataExchange* pDX)
{CDialogEx::DoDataExchange(pDX);DDX_Control(pDX, IDB_OPENFILE, m_btnOpenFile);
}BEGIN_MESSAGE_MAP(CTestDlg, CDialogEx)ON_WM_SYSCOMMAND()ON_WM_PAINT()ON_WM_QUERYDRAGICON()
END_MESSAGE_MAP()// CTestDlg 消息處理程序BOOL CTestDlg::OnInitDialog()
{CDialogEx::OnInitDialog();// 將“關于...”菜單項添加到系統菜單中。// IDM_ABOUTBOX 必須在系統命令范圍內。ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);ASSERT(IDM_ABOUTBOX < 0xF000);CMenu* pSysMenu = GetSystemMenu(FALSE);if (pSysMenu != NULL){BOOL bNameValid;CString strAboutMenu;bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);ASSERT(bNameValid);if (!strAboutMenu.IsEmpty()){pSysMenu->AppendMenu(MF_SEPARATOR);pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);}}// 設置此對話框的圖標。  當應用程序主窗口不是對話框時,框架將自動//  執行此操作SetIcon(m_hIcon, TRUE);			// 設置大圖標SetIcon(m_hIcon, FALSE);		// 設置小圖標// TODO: 在此添加額外的初始化代碼AdjustButtonSize(m_btnOpenFile);return TRUE;  // 除非將焦點設置到控件,否則返回 TRUE
}void CTestDlg::OnSysCommand(UINT nID, LPARAM lParam)
{if ((nID & 0xFFF0) == IDM_ABOUTBOX){CAboutDlg dlgAbout;dlgAbout.DoModal();}else{CDialogEx::OnSysCommand(nID, lParam);}
}// 如果向對話框添加最小化按鈕,則需要下面的代碼
//  來繪制該圖標。  對于使用文檔/視圖模型的 MFC 應用程序,
//  這將由框架自動完成。void CTestDlg::OnPaint()
{if (IsIconic()){CPaintDC dc(this); // 用于繪制的設備上下文SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);// 使圖標在工作區矩形中居中int cxIcon = GetSystemMetrics(SM_CXICON);int cyIcon = GetSystemMetrics(SM_CYICON);CRect rect;GetClientRect(&rect);int x = (rect.Width() - cxIcon + 1) / 2;int y = (rect.Height() - cyIcon + 1) / 2;// 繪制圖標dc.DrawIcon(x, y, m_hIcon);}else{CDialogEx::OnPaint();}
}//當用戶拖動最小化窗口時系統調用此函數取得光標
//顯示。
HCURSOR CTestDlg::OnQueryDragIcon()
{return static_cast<HCURSOR>(m_hIcon);
}int  CTestDlg::CalBtnTextWidth(CButton &btn)
{// 獲取設備上下文CPaintDC dc(&btn);// 獲取按鈕的文本CString strText;btn.GetWindowText(strText);// 計算文本的大小RECT rectText = { 0, 0, 0, 0 };dc.DrawText(strText, &rectText, DT_CALCRECT | DT_SINGLELINE);// 返回文本的寬度return rectText.right - rectText.left + 20;
}void CTestDlg::AdjustButtonSize(CButton &btn)
{int nBtnTextWidth = CalBtnTextWidth(btn);WINDOWPLACEMENT sBtnOpenFile;GetDlgItem(IDB_OPENFILE)->GetWindowPlacement(&sBtnOpenFile);sBtnOpenFile.rcNormalPosition.left = sBtnOpenFile.rcNormalPosition.right - nBtnTextWidth;GetDlgItem(IDB_OPENFILE)->SetWindowPlacement(&sBtnOpenFile);
}

擴展:

如果多個控件顯示在一行,排版布局優化:

#include <array>std::array<int, 3> buttonIDs = { IDB_OPENFILE, IDB_OPENFILE1, IDB_OPENFILE2 };
std::array<CButton*, 3> buttons = { &m_btnOpenFile, &m_btnOpenFile1, &m_btnOpenFile2 };
void CTestDlg::AdjustButtonSize(CButton &btn)
{WINDOWPLACEMENT btnPlacement;for (size_t i = 0; i < buttonIDs.size(); i++){// 獲取按鈕的窗口信息GetDlgItem(buttonIDs[i])->GetWindowPlacement(&btnPlacement);// 計算文本寬度int nBtnTextWidth = CalBtnTextWidth(*buttons[i]);// 計算按鈕的初始寬度int initWidth = btnPlacement.rcNormalPosition.right - btnPlacement.rcNormalPosition.left;// 選擇新寬度(取最大值)int newWidth = max(initWidth, nBtnTextWidth);// 重新計算左邊界btnPlacement.rcNormalPosition.right = btnPlacement.rcNormalPosition.left + newWidth;// 更新按鈕位置GetDlgItem(buttonIDs[i])->SetWindowPlacement(&btnPlacement);} 
}

Tab控件:

1.計算每個標簽頁的大小

int CalTabTextWidth(CTabCtrl& tabCtrl, int nIndex)
{// 獲取設備上下文CClientDC dc(&tabCtrl);CFont* pOldFont = dc.SelectObject(tabCtrl.GetFont()); // 使用 Tab 控件的字體// 獲取頁簽文本TCITEM item;TCHAR text[256] = { 0 };item.mask = TCIF_TEXT;item.pszText = text;item.cchTextMax = _countof(text);if (!tabCtrl.GetItem(nIndex, &item)){dc.SelectObject(pOldFont); // 還原字體return 0; // 獲取失敗返回 0}// 計算文本尺寸RECT rectText = { 0, 0, 0, 0 };dc.DrawText(text, &rectText, DT_CALCRECT | DT_SINGLELINE);dc.SelectObject(pOldFont); // 恢復原來的字體// 返回文本寬度(加上一些間距)return (rectText.right - rectText.left) + 20; // 額外增加 20 像素以適應邊距
}

2.獲取單個頁簽的初始寬度

// 獲取單個頁簽的初始寬度
int GetTabInitialWidth(CTabCtrl& tabCtrl, int nIndex)
{CRect rectItem;if (tabCtrl.GetItemRect(nIndex, &rectItem)){return rectItem.Width(); // 獲取頁簽初始寬度}return 0;
}

3.調整每個頁簽的寬度,確保不小于初始寬度

// 調整每個頁簽的寬度,確保不小于初始寬度
void AdjustTabWidth(CTabCtrl& tabCtrl)
{int tabCount = tabCtrl.GetItemCount();for (int i = 0; i < tabCount; i++){int textWidth = CalTabTextWidth(tabCtrl, i); // 計算文本寬度int initialWidth = GetTabInitialWidth(tabCtrl, i); // 獲取初始寬度// 確保頁簽寬度不小于初始寬度if (textWidth < initialWidth){textWidth = initialWidth; // 使用初始寬度}// 設置每個頁簽的寬度tabCtrl.SetItemSize(CSize(textWidth, 30)); // 只調整寬度,保持原高度}
}
  1. 調用模塊
// 在 OnInitDialog 或 OnCreate 中調用
BOOL CMyDialog::OnInitDialog()
{CDialogEx::OnInitDialog();AdjustTabWidth(m_tabCtrl); // 調整頁簽寬度return TRUE;
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/71237.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/71237.shtml
英文地址,請注明出處:http://en.pswp.cn/web/71237.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

SpringBoot 整合mongoDB并自定義連接池,實現多數據源配置

要想在同一個springboot項目中使用多個數據源&#xff0c;最主要是每個數據源都有自己的mongoTemplate和MongoDbFactory。mongoTemplate和MongoDbFactory是負責對數據源進行交互的并管理鏈接的。 spring提供了一個注解EnableMongoRepositories 用來注釋在某些路徑下的MongoRepo…

軟件測試中的BUG

文章目錄 軟件測試的生命周期BugBug 的概念描述 Bug 的要素案例Bug 級別Bug 的生命周期與開發產生爭執怎么辦&#xff1f;【高頻面試題】先檢查自身&#xff0c;Bug 是否描述的不清楚站在用戶角度考慮并拋出問題Bug 的定級要有理有據提?自身技術和業務水平&#xff0c;做到不僅…

泵吸式激光可燃氣體監測儀:快速精準守護燃氣管網安全

在城市化進程加速的今天&#xff0c;燃氣泄漏、地下管網老化等問題時刻威脅著城市安全。如何實現精準、高效的可燃氣體監測&#xff0c;守護“城市生命線”&#xff0c;成為新型基礎設施建設的核心課題。泵吸式激光可燃氣體監測儀&#xff0c;以創新科技賦能安全監測&#xff0…

第J3-1周:DenseNet算法 實現乳腺癌識別

文章目錄 一、前言二、前期準備1.設置GPU2.劃分數據集 三、搭建網絡模型1.DenseLayer模塊2.DenseBlock模塊3.Transition模塊4.構建DenseNet5.構建densenet121 四、訓練模型1.編寫訓練函數2.編寫測試函數3.正式訓練 五、結果可視化1.Loss與Accuracy圖2.模型評估 總結&#xff1a…

【JAVA面試題】== 和 equals() 的區別與使用場景

在 Java 面試中&#xff0c; 和 equals() 的區別是一個高頻考點。理解它們的底層原理和使用場景&#xff0c;對于掌握 Java 基礎知識至關重要。本文將從 基本概念、底層實現 和 實際應用 三個方面&#xff0c;深入解析 和 equals() 的區別。 1. 基本概念 1.1 運算符 作用&a…

-bash: lsof: command not found

一、問題說明 執行如下命令時報錯&#xff1a; # lsof |grep deleted > deleted_file -bash: lsof: command not found二、處理方法 # yum -y install lsof安裝完成后可成功執行上面的命令。

攝像頭應用編程(三):多平面視頻采集

文章目錄 1、前言2、環境介紹3、步驟4、應用程序編寫5、測試5.1、編譯應用程序5.2、運行應用程序 6、總結 1、前言 在查看攝像頭類型時&#xff0c;大致可以分為兩類&#xff1a;Video Capture 和 Video Capture Multiplanar。 本次應用程序主要針對類型為Video Capture Multi…

本地部署 Traefik 的完整教程

Traefik 是一款現代化的反向代理和負載均衡工具,專為云原生環境設計。它支持自動服務發現、動態配置更新以及多種后端(如 Docker、Kubernetes、Consul 等)。本教程將指導你如何在本地部署 Traefik,并配置其作為反向代理和負載均衡器。 1. 準備工作 在開始之前,請確保你的…

三維數據可視化與表面重建:Marching Cubes算法的原理與應用

1. 引言 隨著現代醫學影像技術的飛速發展&#xff0c;三維數據的可視化與重建已成為醫學研究、臨床診斷和手術規劃的重要工具。在眾多三維重建算法中&#xff0c;Marching Cubes算法因其高效、穩定的特性成為從離散數據場中提取等值面的經典方法。本報告將深入探討Marching Cu…

MySql面試總結(二)

WHERE 子句優化 截至2024年7月,MySQL最新穩定版本是8.2,并不存在MySQL 8.4 。下面從常見的幾個方面為你介紹 MySQL 8.x 中 WHERE 子句的優化方法: 1. 確保使用索引 原理:索引可以加快數據的查找速度,當 WHERE 子句中的條件列有索引時,MySQL 可以直接定位到符合條件的數…

【圖論】判斷圖中有環的兩種方法及實現

判斷圖中有環的兩種方法及實現 在圖論中&#xff0c;檢測有向圖是否存在環是常見問題。本文將介紹兩種主流方法&#xff1a;DFS三色標記法和拓撲排序&#xff08;Kahn算法&#xff09;&#xff0c;并提供對應的C代碼實現。 方法一&#xff1a;DFS三色標記法 核心思想 通過深…

11.【線性代數】——矩陣空間,秩1矩陣,小世界圖

十一 矩陣空間&#xff0c;秩1矩陣&#xff0c;小世界圖 1. 矩陣空間交集 和 和集 2. 所有解空間3. r 1 r1 r1的矩陣4. 題目5. 小世界圖 空間&#xff1a;組成空間的元素的線性組合都在這個空間中。 1. 矩陣空間 舉例&#xff1a;矩陣空間&#xff08; M M M 所有3x3的矩陣&…

【網絡安全 | 滲透測試】GraphQL精講一:基礎知識

未經許可,不得轉載, 文章目錄 GraphQL 定義GraphQL 工作原理GraphQL 模式GraphQL 查詢GraphQL 變更(Mutations)查詢(Queries)和變更(Mutations)的組成部分字段(Fields)參數(Arguments)變量別名(Aliases)片段(Fragments)訂閱(Subscriptions)自省(Introspecti…

關于虛擬環境中遇到的bug

conda和cmd介紹 介紹 Conda 概述&#xff1a; Conda是一個開源包管理系統和環境管理系統&#xff0c;尤其適用于Python和R語言的開發環境。它允許用戶創建獨立的虛擬環境&#xff0c;方便地管理依賴包和軟件版本。 特點&#xff1a; 環境管理&#xff1a;可以創建、導入、導…

基于nginx的灰度發布解決方案

Nginx 在灰度發布中可以看作是一個精確的流量調度員&#xff0c;它充當著客戶端與后端服務器之間的中介。通過配置好的規則&#xff0c;Nginx 會將用戶請求智能地引導到不同版本的服務上。這樣&#xff0c;Nginx 可以根據具體需求靈活地分配流量&#xff0c;確保新版本逐步推向…

網絡安全法與等級保護 PPT 精華匯總

資源描述 本資源文件為《網絡安全法與等級保護》的PPT精華匯總&#xff0c;內容涵蓋了網絡安全法與等級保護的總體框架及相關標準規范。該PPT詳細介紹了網絡安全法與等級保護的各個章節和條款&#xff0c;并提供了基礎類和應用類的相關標準文件&#xff0c;幫助讀者全面了解和…

uni-app開發安卓和iOS 打包流程(云打包)

首先講一下安卓打包的流程,之后再說ios。打包安卓和iOS打包的流程有些不同,安卓打包相對來說比較簡單,而iOS打包需要更多的準備工作,如申請開發者賬號、生成證書等。 一、安卓打包 1、安卓打包直接在window電腦上就可以操作,打開hbuilderx,找到你的項目選中,然后點擊發…

攝像頭應用編程(四):ARM Linux LCD實時預覽UVC攝像頭畫面

文章目錄 1、前言2、環境介紹3、步驟4、應用程序編寫4.1、lcd初始化4.2、攝像頭初始化4.3、jpeg解碼4.4、開啟攝像頭4.5、完整的程序如下 5、測試5.1、編譯應用程序5.2、運行應用程序 6、總結 1、前言 本次應用程序主要針對支持MJPEG格式輸出的UVC攝像頭。 2、環境介紹 rk35…

藍橋與力扣刷題(藍橋 k倍區間)

題目&#xff1a;給定一個長度為 N 的數列&#xff0c;A1,A2,?AN?&#xff0c;如果其中一段連續的子序列 Ai,Ai1,?Aj( i≤j ) 之和是 K 的倍數&#xff0c;我們就稱這個區間[i,j] 是 K 倍區間。 你能求出數列中總共有多少個 K 倍區間嗎&#xff1f; 輸入描述 第一行包含兩…

json介紹、python數據和json數據的相互轉換

目錄 一 json介紹 json是什么&#xff1f; 用處 Json 和 XML 對比 各語言對Json的支持情況 Json規范詳解 二 python數據和json數據的相互轉換 dumps() : 轉換成json loads(): 轉換成python數據 總結 一 json介紹 json是什么&#xff1f; 實質上是一條字符串 是一種…