常用MFC控件基础使用(Edit Button Check Combo Tree 显示位图 控件大小自适应、线程、右键菜单、控件调整移动、MFC背景)

本文围绕MFC展开,介绍了多种控件的使用,如Edit Control、Button控件、Check控件等,还涉及快捷键设置、显示缓冲区位图、窗口自适应大小等功能的实现方法,以及线程快速使用、界面右键悬浮菜单等内容,同时提到屏蔽enter和esc防止程序退出。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


本文总结常用MFC控件使用方法,具体使用方法网上一箩筐,这里不在赘述,仅供查询常用函数,文章持续更新,阅读者不可依葫芦画瓢,还应举一反三

1.Edit Control

文本输入控件,功能是显示或设置参数,主要涉及参数类型的转换,设置显示值等
,此外还可以设置相关事件函数,如销毁焦点或值变化时执行不同的函数

CString Val;
int num=10;
GetDlgItemText(IDC,Val);//获取控件IDC值并将值传给Val
SetDlgItemText(IDC,Val);//将Val值写给控件
GetDlgItem(IDC)->SetWindowTextW(Val);//显示Val在IDC控件上
GetDlgItem(IDC)->GetWindowTextW(Val);//获取控件IDC值并将值传给Val
m_Edit.SetWindowTextW(Val);//显示Val在IDC控件上
m_Edit.GetWindowTextW(Val);//获取控件成员m_Edit中的值并将值传给Val
num=_ttoi(Val);//将值Val转换为int类型赋给num,亦有_ttof,_wtoi等指令
Val.Format(_T("%d"),num);//将值num格式化输出给Val

2.Button控件

和Edit控件一样,Button控件也可以根据场景设置响应函数,如按下、双击等,亦可以添加成员变量CButton,通过成员或者IDC设置控件状态如是否可点击:

CButton m_Btn;//事先设置了IDC_BTN的控件变量
GetDlgItem(IDC_BTN)->EnableWindow(FALSE);//控件变灰,不可点击
m_Btn.EnableWindow(TRUE);//控件变亮,可点击

3.Check控件

Check为复选框控件,是一种在二选一时分路执行程序的控件

int state = m_check.GetCheck();//判断是否勾选,并将状态传给state
m_check.SetCheck(0);//0未勾选,1为勾选,并且一般在参数是布尔变量时用0或FALSE表示非,1与TRUE表示真
m_check.SetCheck(TRUE);//真,表示勾选

if (BST_CHECKED == IsDlgButtonChecked(IDC_CHECK))
//判断Check控件是否处于BST_CHECKED状态,并根据情况执行不同code
{
       //Your Code
}
else
{
//Your Code
}

4.Combo Box

下拉框控件,通过该控件可以在多个参数中快速选择所需参数,可判断参数索引值或框文本内容实现不同的code功能。组合框(ComboBox)的本质是文本框(TextBox)和列表框(ListBox)的组合。
组合框的属性方法和事件与文本框和列表框的大多数用法一致。

m_Combo.AddString(_T("1"));//自动从末行添加字符串,m_Combo为控件变量
m_Combo.InsertString(1,_T("2"));//在索引1位置显示字符2
m_Combo.DeleteString(n)//删除第n行
m_Combo.ResetContent();//可以删除列表框中所有行。
m_Combo.GetCount();//得到当前列表框中行的数量。
m_Combo.GetLBText(n,str);//获取n行内容并赋值给str
m_COmbo.FindString(n,str);//从第n行开始查找str内容,若查找到则返回所在位置
m_Combo.SetCurSel(n);//设置第n行内容为显示的内容。
int Sel=m_Combo.GetCurSel();//获取当前显示行所在索引值

5.Tree 控件

CTreeCtrl m_Tree;//控件变量
HTREEITEM Root_Sub[10];//十个一级树
HTREEITEM Root_Sub_sub[10];//十个二级树
Root_Sub[0] = m_ServerTree.InsertItem(L"这是第一个一级树", 1, 0, TVI_ROOT);//添加一个一级树
Root_Sub[1] = m_ServerTree.InsertItem(L"这是第二个一级树", 1, 0, TVI_ROOT);//添加一个一级树
Root_Sub_sub[0] = m_ServerTree.InsertItem(L"这是一级树Root_Sub[0]的第一个二级树", 1, 0, Root_Sub[0]);
Root_Sub_sub[1] = m_ServerTree.InsertItem(L"这是一级树Root_Sub[0]的第二个二级树", 1, 0, Root_Sub[0]);/
///后续以此类推不再赘述

5.快捷键设置

定义一个成员变量

HACCEL m_hAccel;

OnInitDialog()方法里进行初始化:

m_hAccel = LoadAccelerators(AfxGetResourceHandle(),
MAKEINTRESOURCE(IDR_ACCELERATOR1));

类向导增加消息函数PreTranslateMessage

BOOL CXXXDlg::PreTranslateMessage(MSG* pMsg)
{
    if (WM_KEYFIRST <= pMsg->message && pMsg->message <= WM_KEYLAST) 
    { 
        HACCEL hAccel = m_hAccel; 
        if (hAccel && ::TranslateAccelerator(m_hWnd, hAccel, pMsg)) 
            return TRUE; 
    } 
    return CDialog::PreTranslateMessage(pMsg);
}

6 显示缓冲区位图

1.在Dlg.h中加入

	CRect			 rcRect;
	HDC				 m_hDC;
	byte* m_pRawBuffer;
	BITMAPINFO* m_pBitmapInfo;

2.在初始化代码加入

	GetDlgItem(IDC_STATIC_IMGSTREAM)->GetWindowRect(rcRect);
	ScreenToClient(rcRect);
	m_hDC = GetDC()->GetSafeHdc();

3.添加显示函数(以宽度为基准保持显示比例不变,需要创建位图信息)

//显示
void CXXXDlg::ShowImg()
{

	double rcrate = (double)m_nDataHeight/(double)m_nDataWidth;
	SetStretchBltMode(m_hDC, COLORONCOLOR);
	StretchDIBits(m_hDC,
		rcRect.left,
		rcRect.top,
		rcRect.Width(),
		rcrate* rcRect.Width(),
		0,
		0,
		m_nDataWidth,
		m_nDataHeight,
		m_pRawBuffer,//byte*
		m_pBitmapInfo,//BITMAPINFO*
		DIB_RGB_COLORS,
		SRCCOPY
	);
}

7 窗口自适应大小

1.XXDlg.h文件中加入

	//控件Rect表
	CList<CRect, CRect&> m_listRect;

2.初始化代码中加入

	/// /-----------------控件大小自适应---------------------//
	CRect rect;
	GetWindowRect(&rect);
	m_listRect.AddTail(rect);//对话框的区域  

	CWnd* pWnd = GetWindow(GW_CHILD);//获取子窗体  
	while (pWnd)
	{
		pWnd->GetWindowRect(rect);//子窗体的区域  
		m_listRect.AddTail(rect);           //CList<CRect,CRect> m_listRect成员变量  
		pWnd = pWnd->GetNextWindow();//取下一个子窗体  
	}

3.添加消息函数WM_SIZE

void CXXXDlg::OnSize(UINT nType, int cx, int cy)
{
	CDialogEx::OnSize(nType, cx, cy);

	if (m_listRect.GetCount() > 0)
	{
		CRect dlgNow;
		GetWindowRect(&dlgNow);
		POSITION pos = m_listRect.GetHeadPosition();//第一个保存的是对话框的Rect  

		CRect dlgSaved;
		dlgSaved = m_listRect.GetNext(pos);
		ScreenToClient(dlgNow);

		float x = dlgNow.Width() * 1.0 / dlgSaved.Width();//根据当前和之前保存的对话框的宽高求比例  
		float y = dlgNow.Height() * 1.0 / dlgSaved.Height();
		ClientToScreen(dlgNow);

		CRect childSaved;

		CWnd* pWnd = GetWindow(GW_CHILD);
		while (pWnd)
		{
			childSaved = m_listRect.GetNext(pos);//依次获取子窗体的Rect  
			childSaved.left = dlgNow.left + (childSaved.left - dlgSaved.left) * x;//根据比例调整控件上下左右距离对话框的距离  
			childSaved.right = dlgNow.right + (childSaved.right - dlgSaved.right) * x;
			childSaved.top = dlgNow.top + (childSaved.top - dlgSaved.top) * y;
			childSaved.bottom = dlgNow.bottom + (childSaved.bottom - dlgSaved.bottom) * y;
			ScreenToClient(childSaved);
			pWnd->MoveWindow(childSaved);
			pWnd = pWnd->GetNextWindow();
		}
/-------------更新图像显示区域位置----------------
		GetDlgItem(IDC_STATIC_IMGSTREAM)->GetWindowRect(rcRect);
		ScreenToClient(rcRect);
		m_hDC = GetDC()->GetSafeHdc();
/-------------更新图像显示区域位置----------------
	}
}

4.添加GetMinMaxInfo消息控制窗口最大最小值


void CXXXDlg::OnGetMinMaxInfo(MINMAXINFO* lpMMI)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
		/*窗口最小值*/
		if (lpMMI->ptMinTrackSize.x <= 400)
			lpMMI->ptMinTrackSize.x = 400;
		if (lpMMI->ptMinTrackSize.y <= 500)
			lpMMI->ptMinTrackSize.y = 500;
		/*窗口最大值*/
		if (lpMMI->ptMaxTrackSize.x >= 1920)
			lpMMI->ptMaxTrackSize.x = 1920;
		if (lpMMI->ptMaxTrackSize.y >= 1080)
			lpMMI->ptMaxTrackSize.y = 1080;

	CDialogEx::OnGetMinMaxInfo(lpMMI);
}

8 线程快速使用

在CThreadDemoDlg.h下申明定义:

CWinThread* pThread= NULL;//线程指针
HANDLE m_hThread= NULL;//线程句柄
CRITICAL_SECTION m_ThreadLock;//线程锁
static UINT ThreadFunction(LPVOID ptr);//声明线程函数

在初始化代码OnInitDialog()中添加
创建事件并初始化关键帧

m_hThread= CreateEvent(NULL, TRUE, FALSE, NULL);
InitializeCriticalSection(&m_ThreadLock);
if (pThread== NULL)
{
	pThread= AfxBeginThread(ThreadFunction, this);// 创建线程, 线程函数是静态成员函数或全局函数
}

在需要进入线程处理数据的地方添加:

EnterCriticalSection(&m_ThreadLock);//线程锁,进入临界区
//在这个线程尚未执行LeaveCriticalSection之前,其它线程碰到EnterCritialSection语句的话就会处于等待状态,以此保护共享资源的作用。 
//Data Change在此处进行数据交换,交换数据后进入线程对数据做进一步处理
LeaveCriticalSection(&m_ThreadLock);//离开临界区
SetEvent(m_hThread);

线程函数:

UINT ThreadDemoDlg::ThreadFunction(LPVOID ptr)
{
	ThreadDemoDlg* pDemo= (ThreadDemoDlg*)ptr;
	while (1)
	{
		if (WaitForSingleObject(pDemo->m_hThread, INFINITE) == WAIT_OBJECT_0)
		{
			ResetEvent(pDemo->m_hThread);//重置事件
			EnterCriticalSection(&pDemo->m_ThreadLock);//进入关键帧
			//GetLocalTime(&Systm); //do your code
			LeaveCriticalSection(&pDemo->m_ThreadLock);//离开关键帧
		}
	}
	return 0;
}
  DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds ); 
     //hHandle 指明一个内核对象的句柄 
     //dwMilliseconds  等待时间(毫秒)
  1. 参数一:该函数需要传递一个内核对象句柄,该句柄标识一个内核对象,
  • 若该内核对象处于未通知状态,则该函数导致线程进入阻塞状态;
  • 若该内核对象处于已通知状态,则该函数立即返回WAIT_OBJECT_0
  1. 参数二:
  • 1–INFINITE:指明要无限期等待下去,
  • 2–0:函数测试同步对象的状态并立即返回。
  • 3–指定毫秒 若等待超时,该函数返回WAIT_TIMEOUT。 若该函数失败,返回WAIT_FAILED

示例:

DWORD dword = WaitForSingleObject(hProcess, 5000); //等待一个进程结束
switch (dword)
{
case WAIT_OBJECT_0: // hProcess所代表的进程在5秒内结束do...
break; 
case WAIT_TIMEOUT: // 等待时间超过5秒,do...
break; 
case WAIT_FAILED: // 函数调用失败,比如传递了一个无效的句柄do...
break;
}

9 界面右键悬浮菜单

void CXXXDlg::OnContextMenu(CWnd* /*pWnd*/, CPoint point)
{
		// TODO: 在此处添加消息处理程序代码
		RECT rectPic;
		CMenu menu;

		GetDlgItem(IDC_LIST_INFO)->GetWindowRect(&rectPic);
		if (PtInRect(&rectPic, point)) 
		{
			menu.LoadMenu(IDR_MENU_INFO);
			CMenu* pContextMenu = menu.GetSubMenu(0);//获取第一位子菜单
			pContextMenu->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y, this);
		}
}

10 控件矩形框重定位(移动控件和调整大小)

void CXXXDlg::MoveRectCtrl(int nID,CPoint first,CPoint next )
{
	CRect Rect;
	GetDlgItem(nID)->GetWindowRect(Rect);
	ScreenToClient(Rect);
	Rect.SetRect(first, next);
	GetDlgItem(nID)->MoveWindow(Rect, TRUE);
} 

11 MFC从文件读取位图作为背景

注意必须位图文件!

BOOL CXXXDlg::OnEraseBkgnd(CDC* pDC)
{ 
	//设定背景图像
	HBITMAP  hBmp;
	CBitmap c_bmp; 
	BITMAP   bmp;
	CRect rect;
	CDC dcCompatible;

	GetClientRect(&rect);
	hBmp = (HBITMAP)::LoadImage(AfxGetInstanceHandle(), _T("bkgnd.bmp"), IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
	c_bmp.DeleteObject();
	c_bmp.Attach(hBmp);

	c_bmp.GetBitmap(&bmp);
	
	dcCompatible.CreateCompatibleDC(pDC);
	dcCompatible.SelectObject(c_bmp);

	//pDC->BitBlt(0,0,rect.Width(),rect.Height(),&dcCompatible,0,0,SRCCOPY);
	pDC->StretchBlt(0, 0, rect.Width(), rect.Height(), &dcCompatible, 0, 0,
		bmp.bmWidth, bmp.bmHeight, SRCCOPY); 
	return true;//这一句不能少
	//return CDialogEx::OnEraseBkgnd(pDC);
}

12 屏蔽enter & esc防止程序退出

BOOL   CDemoDlg::PreTranslateMessage(MSG   *pMsg)  
  {  
          if(pMsg->message   ==   WM_KEYDOWN)  
          {  
                  switch(pMsg->wParam)  
                  {  
                  case   VK_RETURN://屏蔽回车  
                          //   OnKeyDown(VK_SPACE,   LOWORD(pMsg   ->lParam),   HIWORD(pMsg->lParam));    
                          return   TRUE;  
                  case   VK_ESCAPE://屏蔽Esc  
                          return   TRUE;  
                  }  
          }  
          return   CDialog::PreTranslateMessage(pMsg);  
  } 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值