MFC经验

article/2025/10/22 1:07:57

MFC框架各部分指针获取方式:

  记住,是获取指针

 

MFC消息流程图:

string CString char* 的互相转换:

   

    string 转 CString  
  CString.Format("%s", string.c_str());  //用c_str()比data()好  
  char 转 CString  
  CString.Format("%s", char*);  // 可以直接给CString赋值 ,不要用Format
  
 
  char* 转 string  
  string s(char *);       
  CString 转 string  
  string s(CString.GetBuffer());  //测试显示 可以直接用CString 赋给string ,
//因CString 有operator LPCTSTR 不拷贝 只返回指针


  string 转 char *  
  char *p = string.c_str();  
    CString 转char *
    CString.GetBuffer();

   可直接赋值,不用转换,因为LPCTSTR在CString中被重载了.

 

 一条重要经验:

 如果我们的类/结构体中有CArray(或CList等其他的派生自CObject类,即很多的控件类)的成员变量,我们最好添加上一个public类型的operator=运算赋重载函数,否则编译器报错 error C2248: “CObject::operator =”: 无法访问 private 成员(在“CObject”类中声明)

 创建全屏窗口:

    win.CreateEx(0, szProgram, szProgram,
              WS_POPUP,
              0, 0,
              GetSystemMetrics( SM_CXSCREEN ),
              GetSystemMetrics( SM_CYSCREEN ),
              NULL, NULL, hInst);
       

目录对话框SHBrowseForFolder:

CString sFolderPath;
 BROWSEINFO bi;
 TCHAR Buffer[MAX_PATH];
 //初始化入口参数bi开始
 bi.hwndOwner = NULL;
 bi.pidlRoot = NULL;
 bi.pszDisplayName = Buffer;//此参数如为NULL则不能显示对话框
 bi.lpszTitle = _T("选择路径");
 bi.ulFlags = BIF_RETURNONLYFSDIRS;
 bi.lpfn = NULL;
 bi.iImage = 0;
 //初始化入口参数bi结束
 LPITEMIDLIST pIDList = SHBrowseForFolder(&bi);//调用显示选择对话框
 if(pIDList)
 {
  SHGetPathFromIDList(pIDList, Buffer);
  //取得文件夹路径到Buffer里
  sFolderPath = Buffer;//将路径保存在一个CString对象里
 }

 

CTreeCtrl使用图标:

一种最简单的方法:
1.在资源管理器中建立ICON;如:IDI_ICON_DEVICE,IDI_ICON_DEVICE_SEL; 
2.在CTreeCtrlEx中增加成员变量:CImageList m_ImageList; 
3.在void CLocTreeView::OnInitialUpdate()中增加如下代码:
m_ImageList.Create(16,16,ILC_COLOR32,2,2); 
m_ImageList.Add( AfxGetApp()->LoadIcon(IDI_ICON_DEVICE)); 
m_ImageList.Add( AfxGetApp()->LoadIcon(IDI_ICON_DEVICE_SEL)); 
m_oTreeCtrl.SetImageList(&m_ImageList,TVSIL_NORMAL);
4.在向树中插入Item时指定这个Item对应的ICON位图,代码如下:
      HTREEITEM hCurItem = m_oTreeCtrl.InsertItem( "ItemContent",0,1, hItemParent);//参数中0,1为icon的索引
其中的0指添加好后的图片为IDI_ICON_DEVICE,选中后显示的图片为:IDI_ICON_DEVICE_SEL;

 

CTreeCtrl使用图标 另:

建立一个CTreeCtrl控制成员 m_Tree;

使用图标的方法:

Step1:   //load icon

HICON icon[4];

Icon[0]=AfxGetApp()->LoadIcon(IDI_ICON1);

Icon[1]=AfxGetApp()->LoadIcon(IDI_ICON2);

Step2: //创建CImageList

CImageList *ImageList4Tree = new CImageList;

ImageList4Tree.Create(16,16,0,4,4); //16,16为图标分辩率,4,4为该list最多能容纳的图标数

For(int i=0;i<2;i++)

{

       ImageList4Tree->Add(Icon[i]); //读入图标

}

Step3: //使用创建好的CImageList

m_Tree.SetImageList(ImageList4Tree);

Step4: //在添加项的同时选用图标

m_Tree.InsertItem(itemName,0,1,parentItem); //第2个参数是item在添加好后的图标   //第3个参数为item在被选中后的图标

 

树一次展开所有结点:

主要思想是递归。

01 void CMenuCreatDlg::OnMENUITEMexpandtree() //展开所有节点
02 {
03 // TODO: Add your command handler code here
04 MyExpandTree(m_tree.GetRootItem());
05 }
06 void CMenuCreatDlg::MyExpandTree(HTREEITEM hTreeItem)
07 {
08 if(!m_tree.ItemHasChildren(hTreeItem))
09 {
10 return;
11 }
12 HTREEITEM hNextItem = m_tree.GetChildItem(hTreeItem);
13 while (hNextItem != NULL)
14 {
15 MyExpandTree(hNextItem);
16 hNextItem = m_tree.GetNextItem(hNextItem, TVGN_NEXT);
17 }
18 m_tree.Expand(hTreeItem,TVE_EXPAND);
19 }
1 <p> </p>
2 <p> </p><p>void ExpandBranch(HTREEITEM hItem,CTreeCtrl& tree,<br>                 BOOL bExpand /*=TRUE*/)</p><p>/* bExpand =TRUE 展开所有节点,否则为折叠*/<br>{<br>   if (tree.ItemHasChildren(hItem))<br>   {<br>      tree.Expand(hItem,bExpand?TVE_EXPAND:TVE_COLLAPSE);<br>      hItem=tree.GetChildItem(hItem);<br>      do <br>      {<br>         ExpandBranch(hItem,tree);<br>      } while((hItem=tree.GetNextSiblingItem(hItem))!=NULL);<br>   }<br>}<br></p><p>
3 </p><strong> 给树控件添加右键菜单:</strong>
4 <p> </p><p>首先定义右键消息函数:</p><p>    afx_msg  void  OnRBClick(NMHDR* pNMHDR, LRESULT* pResult);    </p><p>    然后在消息循环中定义消息对应关系:</p><p>    ON_NOTIFY(NM_RCLICK, ID_TREECTRL, OnRbClick)</p><p>    接着定义消息函数内容:</p><p> </p><p>void CXMLEditorDlg::OnNMRClickTree(NMHDR *pNMHDR, LRESULT *pResult)<br>{<br> // TODO: 在此添加控件通知处理程序代码<br> *pResult = 0;</p><p> CPoint point;<br> GetCursorPos(&point);<br> CPoint pointInTree = point;<br> m_TreeCtrl.ScreenToClient(&pointInTree);<br> UINT flag = TVHT_ONITEM;<br> HTREEITEM hItem = m_TreeCtrl.HitTest(pointInTree, &flag);</p><p> m_hSelectedItem = hItem;<br> if(hItem != NULL)<br> {<br>  //m_TreeCtrl.SelectItem(hItem);<br>  CMenu menu;<br>  menu.LoadMenu(IDR_TREE);<br>  menu.GetSubMenu(0)->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y, this, NULL);<br> }<br>}</p><p><strong> vs2005导入GIF图片:</strong></p><p>用源码编辑器打开.rc文件.添加如下</p><p>IDR_EYES                GIF                     "res\\eyes.gif"<br>IDR_FELIX               GIF                     "res\\felix_new.gif"<br>IDR_TYPE                GIF                     "res\\type.gif"</p><p>然后 在resource.h中 添加 ID定义</p><p>#define IDC_HAND                        133<br>#define IDR_EYES                        134<br>#define IDR_TYPE                        137</p><p> </p><p>下边的也行:</p><p> </p><p><br>手工在.rc文件里添加<br>IMG1 IMAGE "res\\test.gif"</p><p>在load时可以这样:<br><span style="color: red">hResInfo = FindResource(hInst , "IMG1", "IMAGE");</span><br>if (hResInfo == NULL)  <br>{<br>dwErr = GetLastError();<br>return FALSE;<br>}</p><p>// Load the resource<br><span style="color: red">hRes = LoadResource(hInst , hResInfo);</span><br>if (hRes == NULL)  <br>{<br>dwErr = GetLastError();<br>return FALSE;<br>}<br></p><p> </p><p><span style="color: #000000"><strong>基于对话框程序添加菜单:</strong></span></p>

在VC中创建一个基于对话框的MFC程序,要在其中添加菜单总共分三步:

1、首先插入一个菜单资源IDR_MENU,然后可以编辑修改菜单;

2、 然后在为对话框添加一个CMenu类型的成员变量m_Menu;

3、在OnInitDialog()中添加如下的代码:

      m_Menu.LoadMenu(IDR_MENU);    //载入菜单
      SetMenu(&m_Menu);                    //显示菜单

经过这三步以后菜单就可以显示出来了。

菜单退出项消息映射:

 BEGIN_MESSAGE_MAP(CXMLApp, CWinApp)
   ON_COMMAND(ID_HELP, &CWinApp::OnHelp)
   ON_COMMAND(ID_EXIT, &CWinApp::OnAppExit)
END_MESSAGE_MAP()

四,基于对话框程序添加工具栏:

1、添加工具栏资源ID为IDR_TOOLBAR
2、在对话框的类定义中加:
 CToolBar m_ToolBar;
3、在OnInitDialog中或其它合适的消息响应中加如下代码:

 m_ToolBar.Create(this);
 m_ToolBar.LoadToolBar(IDR_TOOLBAR1);
 //控件条定位
 RepositionBars(AFX_IDW_CONTROLBAR_FIRST,AFX_IDW_CONTROLBAR_LAST,0); 

 

4、手工添加处理函数
 

   afx_msg void OnBtnXXX();//消息响应函数声明
    ON_COMMAND(ID_BTN_XXX/*工具按钮ID*/,OnBtnXXX/*函数名*/)//消息映射
      void CXXXDlg::OnBtnXXX(){}//消息处理函数

 

RichEdit初始化,不然不会显示(程序会没有界面弹出来):

AfxEnableControlContainer();  //原有
 AfxInitRichEdit();                 //richedit的初始化  在app类InitInstance中

 

对话框右上角?号图标:

只需要在对话框属性上选中Context Help这个选项就OK了,把对话框显示出来就能发现右上角的小问号按钮。



 

应用程序只有一个实例:

在app类的InitInstance()中添加如下代码:

 BOOL bAlreadyRunning = FALSE;

 HANDLE hMutexOneInstance = ::CreateMutex( NULL, FALSE, _T("SnowParentWindow"));
 bAlreadyRunning = ( ::GetLastError() == ERROR_ALREADY_EXISTS || ::GetLastError() == ERROR_ACCESS_DENIED);

 if(bAlreadyRunning)
  return FALSE;

 

图标菜单(菜单图标)的实现:

一、单文档的菜单图标实现: 
1、新建一个位图资源,大小为13*13(#add暂时必须满足这个条件,大的图标不会显示),假设ID为IDB_BITMAP1,画好图标 
2、在CMainFrame中添加成员变量:CBitmap bitmap 
3、在CMainFrame的OnCreate中加入: 
bitmap.LoadBitmap(IDB_BITMAP1); 
GetMenu()->GetSubMenu(0)->SetMenuItemBitmaps(0,MF_BYPOSITION, &bitmap, &bitmap);//具体哪个菜单项为图标,可自己设定 
4、编译,实现图标菜单。

二、多文档的菜单图标实现: 
1、新建一个位图资源,大小为13*13,假设ID为IDB_BITMAP1,画好图标 
2、在CMaoyeah_comDoc(你程序中的CDocument子类)中添加成员变量:CBitmap bitmap 
3、在CMaoyeah_comDoc的OnNewDocument中加入: 
bitmap.LoadBitmap(IDB_BITMAP1); 
CMenu *pMenu; 
pMenu = CMenu::FromHandle(((CMultiDocTemplate *)m_pDocTemplate)->m_hMenuShared); 
CMenu *pSubMenu = pMenu->GetSubMenu(0); 
pSubMenu->SetMenuItemBitmaps(0,MF_BYPOSITION, &bitmap, &bitmap); 
4、编译,实现图标菜单。

 

CEdit控件限定只输入数字:

如果在对话框上创建,可直接在style属性里指定为number,如果动态创建的则

设置Edit的属性为:ES_NUMBER 
比如m_SpeedEdit.ModifyStyle(0,ES_NUMBER,TRUE);

或者


 DWORD     dwStyle   =   m_SpeedEdit.GetStyle();

 dwStyle   |=   ES_NUMBER; 
 SetWindowLong(m_SpeedEdit.m_hWnd, GWL_STYLE, dwStyle);

 

在一个对话框上显示出一条凹下去的线:

把picture控件拉成直线,设置color属性为etched

或者选择sunken属性 为true

 

右键弹出菜单的实现:

通常是响应WM_CONTEXTMENU消息

void CRMenuView::OnContextMenu(CWnd* pWnd, CPoint point)
{
    // TODO: Add your message handler code here
    CMenu m_popMenu;
    m_popMenu.LoadMenu(IDR_MENU1);
    CMenu*   pSubMenu=m_popMenu.GetSubMenu(0);
    pSubMenu->TrackPopupMenu(TPM_LEFTALIGN|TPM_LEFTBUTTON,point.x,point.y,this);
}

 

基于对话框程序大小调整相关:

对话框border属性改为resizing即为可调大小.

控件跟随窗口大小一起变化,响应WM_SIZE消息

限制大小的范围
 
重载WM_GETMINMAXINFO消息 
OnGetMinMaxInfo(MINMAXINFO   FAR*   lpMMI)   
{

        lpMMI-> ptMinTrackSize.x   =   400   ; 
        lpMMI-> ptMinTrackSize.y   =   400   ;

        lpMMI-> ptMaxTrackSize.x   =   500   ; 
        lpMMI-> ptMaxTrackSize.y   =   500   ;

        CDialog::OnGetMinMaxInfo(lpMMI); 
}

 

对话框滚动条属性后的响应:

 

//水平滚动响应
void CChildDlg::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
 // TODO: 在此添加消息处理程序代码和/或调用默认值
 SCROLLINFO scrollinfo;  
 GetScrollInfo(SB_HORZ,&scrollinfo,SIF_ALL);  
 switch (nSBCode)  
 {  
 case SB_LEFT:  
  ScrollWindow((scrollinfo.nPos-scrollinfo.nMin)*10,0);  
  scrollinfo.nPos = scrollinfo.nMin;  
  SetScrollInfo(SB_HORZ,&scrollinfo,SIF_ALL);  
  break;  
 case SB_RIGHT:  
  ScrollWindow((scrollinfo.nPos-scrollinfo.nMax)*10,0);  
  scrollinfo.nPos = scrollinfo.nMax;  
  SetScrollInfo(SB_HORZ,&scrollinfo,SIF_ALL);  
  break;  
 case SB_LINELEFT:  
  scrollinfo.nPos -= 1;  
  if (scrollinfo.nPos<scrollinfo.nMin)
  {  
   scrollinfo.nPos = scrollinfo.nMin;  
   break;  
  }  
  SetScrollInfo(SB_HORZ,&scrollinfo,SIF_ALL);  
  ScrollWindow(10,0);  
  break;  
 case SB_LINERIGHT:  
  scrollinfo.nPos += 1;  
  if (scrollinfo.nPos>scrollinfo.nMax)  
  {  
   scrollinfo.nPos = scrollinfo.nMax;  
   break;  
  }  
  SetScrollInfo(SB_HORZ,&scrollinfo,SIF_ALL);  
  ScrollWindow(-10,0);  
  break;  
 case SB_PAGELEFT:  
  scrollinfo.nPos -= 5;  
  if (scrollinfo.nPos<scrollinfo.nMin)
  {  
   scrollinfo.nPos = scrollinfo.nMin;  
   break;  
  }  
  SetScrollInfo(SB_HORZ,&scrollinfo,SIF_ALL);  
  ScrollWindow(10*5,0);  
  break;  
 case SB_PAGERIGHT:  
  scrollinfo.nPos += 5;  
  if (scrollinfo.nPos>scrollinfo.nMax)  
  {  
   scrollinfo.nPos = scrollinfo.nMax;  
   break;  
  }  
  SetScrollInfo(SB_HORZ,&scrollinfo,SIF_ALL);  
  ScrollWindow(-10*5,0);  
  break;  
 case SB_THUMBPOSITION:  
  break;  
 case SB_THUMBTRACK:  
  ScrollWindow((scrollinfo.nPos-nPos)*10,0);  
  scrollinfo.nPos = nPos;  
  SetScrollInfo(SB_HORZ,&scrollinfo,SIF_ALL);  
  break;  
 case SB_ENDSCROLL:  
  break;  
 } 


 CDialog::OnHScroll(nSBCode, nPos, pScrollBar);
}

 

//垂直滚动响应
void CChildDlg::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
 // TODO: 在此添加消息处理程序代码和/或调用默认值

 if (pScrollBar == NULL)
 {
  //MessageBox("33333333");
 }
 SCROLLINFO scrollinfo;
 GetScrollInfo(SB_VERT,&scrollinfo,SIF_ALL);
 switch (nSBCode)
 {
 case SB_BOTTOM:
  ScrollWindow(0,(scrollinfo.nPos-scrollinfo.nMax)*10);
  scrollinfo.nPos = scrollinfo.nMax;
  SetScrollInfo(SB_VERT,&scrollinfo,SIF_ALL);
  break;
 case SB_TOP:
  ScrollWindow(0,(scrollinfo.nPos-scrollinfo.nMin)*10);
  scrollinfo.nPos = scrollinfo.nMin;
  SetScrollInfo(SB_VERT,&scrollinfo,SIF_ALL);
  break;
 case SB_LINEUP:
  scrollinfo.nPos -= 1;
  if (scrollinfo.nPos<scrollinfo.nMin)
  {
   scrollinfo.nPos = scrollinfo.nMin;
   break;
  }
  SetScrollInfo(SB_VERT,&scrollinfo,SIF_ALL);
  ScrollWindow(0,10);
  break;
 case SB_LINEDOWN:
  scrollinfo.nPos += 1;
  if (scrollinfo.nPos>scrollinfo.nMax)
  {
   scrollinfo.nPos = scrollinfo.nMax;
   break;
  }
  SetScrollInfo(SB_VERT,&scrollinfo,SIF_ALL);
  ScrollWindow(0,-10);
  break;
 case SB_PAGEUP:
  scrollinfo.nPos -= 5;
  if (scrollinfo.nPos<scrollinfo.nMin)
  {
   scrollinfo.nPos = scrollinfo.nMin;
   break;
  }
  SetScrollInfo(SB_VERT,&scrollinfo,SIF_ALL);
  ScrollWindow(0,10*5);
  break;
 case SB_PAGEDOWN:
  scrollinfo.nPos += 5;
  if (scrollinfo.nPos>scrollinfo.nMax)
  {
   scrollinfo.nPos = scrollinfo.nMax;
   break;
  }
  SetScrollInfo(SB_VERT,&scrollinfo,SIF_ALL);
  ScrollWindow(0,-10*5);
  break;
 case SB_ENDSCROLL:
  break;
 case SB_THUMBPOSITION:  //拖动
  ScrollWindow(0,(scrollinfo.nPos-nPos)*10);
  scrollinfo.nPos = nPos;
  SetScrollInfo(SB_VERT,&scrollinfo,SIF_ALL);
  break;
 case SB_THUMBTRACK:
  ScrollWindow(0,(scrollinfo.nPos-nPos)*10);
  scrollinfo.nPos = nPos;
  SetScrollInfo(SB_VERT,&scrollinfo,SIF_ALL);
  break;
 }

 CDialog::OnVScroll(nSBCode, nPos, pScrollBar);
}

 

 

响应WM_MOUSEWHELL消息
BOOL CScrollDemoDlg::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)   
{   
    // TODO: 在此添加消息处理程序代码和/或调用默认值   
    //向下滚   
    if (zDelta == -120)   
    {   
          
      nVscroll += 10;   
      OnVScroll(SB_PAGEDOWN, nVscroll, &m_vScroll);   
    }   
    else if (zDelta == 120)   
    {   
        nVscroll -= 10;   
        OnVScroll(SB_PAGEUP, nVscroll, &m_vScroll);   
           
           
    }   
       
    m_vScroll.MoveWindow(rt_mvScroll, TRUE);   
    return CDialog::OnMouseWheel(nFlags, zDelta, pt);   


 屏蔽ENTER和ESC按键:

/*******************************************************************
函数名称: PreTranslateMessage
描    述: 重载函数,屏蔽回车键
输入参数: 无
输出参数: 无
返    回: 无
说     明:无
*******************************************************************/
BOOL CSystemConfig::PreTranslateMessage(MSG* pMsg)
{
    // TODO: 在此添加专用代码和/或调用基类
    if   (pMsg-> message   ==   WM_KEYDOWN) 
    { 
        if   (pMsg-> wParam   ==   VK_ESCAPE) 
            return   TRUE; 
        if   (pMsg-> wParam   ==   VK_RETURN) 
            return   TRUE; 
    } 

    return CDialog::PreTranslateMessage(pMsg);
}

 

GDI GDI+实现双缓存

 

我们看电视时,看到的屏幕称为OSD层,也就是说,只有在OSD层上显示图像我们才能看到。现在,我需要创建一个虚拟的、看不见但是可以在上面画图(比如说画点、线)的OSD层,我称之为offscreen(后台缓冲区)。这个offscreen存在于内存中,我们在上面画图,这个offscreen上面的东西可以显示在OSD层上,需要一个创建这个offscreen的函数,返回这个offscreen的句柄(整型指针)、宽度、高度、指向新建offscreen数据缓冲区的指针,该缓冲区是一个在函数外创建的offscreen的数据缓冲区,大小是offscreen的高度*宽度*每个像素点数据的大小。闪烁是图形编程的一个常见问题。需要多重复杂绘制操作的图形操作会导致呈现的图像闪烁或具有其他不可接受的外观。双缓冲的使用解决这些问题。双缓冲使用内存缓冲区来解决由多重绘制操作造成的闪烁问题。当启用双缓冲时,所有绘制操作首先呈现到内存缓冲区,而不是屏幕上的绘图图面。所有绘制操作完成后,内存缓冲区直接复制到与其关联的绘图图面。因为在屏幕上只执行一个图形操作,所以消除了由复杂绘制操作造成的图像闪烁。

GDI实现双缓存:  

CClientDC dc(this);
    CDC memdc;
    memdc.CreateCompatibleDC(&dc);

CRect rc;
    GetClientRect(rc);
    CBitmap bmp;
    Bmp.CreateCompatibleBitmap(&dc,rc.Width(),rc.Height());
    CBitmap *oldbmp=memdc.SelectObject(&bmp);

memDC.MoveTo(0,0);
    memDC.LineTo(100,100);

dc.BitBlt(0,0,rc.Width(),rc.Height(),&memdc,0,0,SRCCOPY);

上边演示一段初始时候的例子.

首先给出实现的程序,然后再解释,同样是在OnDraw(CDC *pDC)中:

 

//首先定义一个显示设备对象

CDC MemDC;    

                   

//定义一个位图对象

CBitmap MemBitmap; 

        

//随后建立与屏幕显示兼容的内存显示设备

//这时还不能绘图,因为没有地方画 ^_^

MemDC.CreateCompatibleDC(NULL/*pDc一般用这个,不用NULL*/);

 

  //下面建立一个与屏幕显示兼容的位图,至于位图的大小嘛,可以用窗口的大小,也可以自己定义(如:有滚动条时就要大于当前窗口的大小,在BitBlt时决定拷贝内存的哪部分到屏幕上)

MemBitmap.CreateCompatibleBitmap(pDC,nWidth,nHeight);

 

  //将位图选入到内存显示设备中

  //只有选入了位图(#add一定要bitmap?)的内存显示设备才有地方绘图,画到指定的位图上

CBitmap *pOldBit=MemDC.SelectObject(&MemBitmap);

 

  //先用背景色将位图清除干净,这里我用的是白色作为背景

  //你也可以用自己应该用的颜色

MemDC.FillSolidRect(0,0,nWidth,nHeight,#ffffff);

 

  //绘图

  MemDC.MoveTo(……);

MemDC.LineTo(……);

 

  //将内存中的图拷贝到屏幕上进行显示

pDC->BitBlt(0,0,nWidth,nHeight,&MemDC,0,0,SRCCOPY);

 

  //绘图完成后的清理

  MemBitmap.DeleteObject();

  MemDC.DeleteDC();

/

GDI+实现双缓存的具体步骤

 下面的代码是一个最简单的双缓冲的模板。可以根据需要,做简单的修改即可。

 

Bitmap CacheImage( [Width], [Height] );

Graphics CacheGraphics( &CacheImage );

// CacheImage进行描画

// ......

 

// 获得窗口的Graphics对象

Graphics Graphic( [ Window’s HDC ] );

 

// 将描画好的CacheImage画到窗口上

Graphic.DrawImage( &CacheImage, [Left], [Top] );

 

根据一些简单的测试,双缓冲可以有效的改善图像的处理速度。不过最明显的效果还是降低画面的闪烁程度。

 

另(推荐):

 

1、在内存中建立一块“虚拟画布”:

Bitmap bmp = new Bitmap(600, 600);

 

2、获取这块画布的Graphics 对象指针:

Graphics *gBuf = Graphics.FromImage(bmp);

 

3、在这块内存画布上绘图:

gBuf->FillEllipse(brush, i * 10, j * 10, 10, 10);

 

4、将内存画布画到窗口中

HDC hdc = GetDC(hwnd); 
Graphics g(hdc); 
g.DrawImage(bmp, 0, 0, 100, 200);
ReleaseDC(hwnd, hdc);
delete gBuf;    // 必不可少,否则会内存泄漏

 

另:

1、在内存中建立一块“虚拟画布”:

Bitmap bmp = new Bitmap(600, 600);

2、获取这块内存画布的Graphics引用:

Graphics g = Graphics.FromImage(bmp);

3、在这块内存画布上绘图:

g.FillEllipse(brush, i * 10, j * 10, 10, 10);

4、将内存画布画到窗口中

this->CreateGraphics().DrawImage(bmp, 0, 0);
 

 

另外还可以使用CachedBitmap类来做双缓冲。Graphic也有专门的DrawCachedBitmap方法来描画CachedBitmap。但没有上述的方法灵活。如下:

 

*C++ code*/

RECT rc;

GetClientRect(g_hwnd,&rc);

Bitmap bmp(int(rc.right),int(rc.bottom));

 

Graphics bmpGraphics(&bmp);

bmpGraphics.SetSmoothingMode(SmoothingModeAntiAlias);

 

/*Drawing on bitmap*/

SolidBrush bkBrush(Color(0,0,0));

bmpGraphics.FillRectangle(&bkBrush,0,0,rc.right,rc.bottom);

 

/*Drawing on DC*/

Graphics graphics(hdc);

 

/*Important! Create a CacheBitmap object for quick drawing*/

CachedBitmap cachedBmp(&bmp,&graphics);

graphics.DrawCachedBitmap(&cachedBmp,0,0);

 

以上的绘制代码最区别于网络上其他GDI+实现的一处就是,在最后添加了一个CacheBitmap对象用于快速绘制。

CacheBitmap是一个包含了bmp全部象素,并且针对graphics所关联的DC做过特别优化的位图对象。这点可以从其构造参数上看到。 


 让CSpinButtonCtrl控件嵌入edit控件里边:

如图风格

 

调整edit和cspin控件的tab order 顺序为相邻, 设置cspin 的auto buddy 属性为true即可.

 

我的函数注释:

 

 类头文件中用

//功能说明

 

类的cpp文件中则用:

//==================================================================================
// 功能:    装载指定皮肤
// 参数:    strPath:皮肤路径
// 返回值:  无
// 备注
//==================================================================================

 

GDI一些重要区别:

ReleadDC,是和GetDC()配套使用; 
而DeleteDC,和CreateCompatibleDC配套使用;


DeleteObject,是对用Create_为前缀创建的GDI对象使用的。   (#add,即 分两部分,一部分是CDC有关,另一部分则CGdiObject有关)
比如CreateBitmap(),CreateSolidBrush()等等。。 

对话框透明:

SetWindowLong(m_hWnd, GWL_EXSTYLE, GetWindowLong(m_hWnd, GWL_EXSTYLE)^0x80000); //0x80000 : WS_EX_LAYERED
 HINSTANCE hInst = LoadLibrary("User32.DLL"); // 显式加载DLL
 if (hInst != NULL)
 {
 typedef BOOL (WINAPI *MYFUNC)(HWND, COLORREF, BYTE, DWORD);
 // 取得SetLayeredWindowAttributes函数指针
 MYFUNC pFunc = (MYFUNC)GetProcAddress(hInst, "SetLayeredWindowAttributes");
 if (pFunc != NULL)
 {
 pFunc(m_hWnd,#ece9d8, 256, 1); // 2 : LWA_ALPHA
 }
 FreeLibrary(hInst);
 hInst = NULL;
 }


http://chatgpt.dhexx.cn/article/q15Kk3Er.shtml

相关文章

C++ MFC程序入门

1. 选择“MFC应用程序”,命名后选下一步 2. 点“下一步” 3. 选择“基于对话框” 4. 仅勾选“主框架”

MFC系列 - 第一个MFC入门程序

MFC&#xff0c;多年开发和教学&#xff0c;这门课程&#xff0c;新课改决定将它砍掉&#xff0c;Qt也是我们的趋势&#xff0c;同时在我的Qt系列中详细讲解了Qt的系列教学。MFC虽然很古老&#xff0c;但是还是得佩服微软搞得这套框架&#xff0c;让一代又一代Windows程序员无不…

MFC ActiveX (ocx)控件的开发

前言 ActiveX是Microsoft对于一系列策略性面向对象程序技术和工具的称呼&#xff0c;其中主要的技术是组件对象模型&#xff08;COM&#xff09;。 ActiveX控件是一种实现了一系列特定接口而使其在使用和外观上更象一个控件的COM组件。ActiveX控件这种技术涉及到了几乎所有的CO…

开发基于MFC的应用程序

开发基于MFC的应用程序 本篇将介绍如何开发基于MFC的应用程序。 具体步骤如下&#xff1a; 一&#xff1a;启用VS2019编辑器。 二&#xff1a;点击文件—>新建—>项目 三&#xff1a;MFC应用—>下一步 四&#xff1a;添加项目名称—>创建 五&#xff1a;选择基于对…

MFC简介

1.API Wndows操作系统为我们编写Windows应用程序提供的接口函数----API&#xff0c; //Windows中播放声音的API函数 //PlaySound需要的头文件和库文件 #include <mmsystem.h> #pragma comment(lib, "WINMM.LIB")BOOL PlaySound(LPCSTR pszSound, HMODULE hmo…

C++ mfc

以下是我从其他网站中学的内容&#xff0c;后有相应的网站学习链接地址&#xff0c;可供学习 1.选择菜单项File->New->Project&#xff0c;弹出“New Project”对话框。 2.左侧面板中Installed Templated的Visual C下选择MFC&#xff0c;中间窗口中选择MFC Application&a…

MFC教程

以下是我从其他网站中学的内容&#xff0c;后有相应的网站学习链接地址&#xff0c;可供学习 1.选择菜单项File->New->Project&#xff0c;弹出“New Project”对话框。 2.左侧面板中Installed Templated的Visual C下选择MFC&#xff0c;中间窗口中选择MFC Application&…

MFC简要介绍

一、概念 MFC(MicrosoftFoundationClasses)是微软基础类库的简称&#xff0c;是微软公司实现的一个c类库&#xff0c;主要封装了大部分的windows API函数&#xff0c;vc是 微软公司开发的c/c的集成开发环境&#xff0c;所谓集成开发环境&#xff0c;就是说利用它可以编辑&#…

MFC入门小项目

之前学习MFC的时候就是三天打鱼两天晒网&#xff0c;什么都不记&#xff0c;脑子也不转&#xff0c;完全是代码的搬运工。这次又要从头开始&#xff0c;索性写个博客了。截至目前断断续续更了三十篇blog&#xff0c;文笔依然如此拙劣&#xff0c;实属羞愧。技术尚且肤浅&#x…

C++ MFC简介

介绍MFC之前&#xff0c;需要先介绍几个MFC的概念。 1) API Windows操作系统提供了各种各样的函数&#xff0c;以方便我们开发Windows应用程序。这些程序是Windows操作系统提供给应用程序编程的接口&#xff08;Application Programming Interface&#xff09;,简称为API函数…

一、MFC介绍

一、什么是MFC MFC(全称:Microsoft Foundation Classes),微软基础类库。他封装了Windows应用程序的各种API以及相关机制的c++类库。 1、特点: (1)开发效率高 (2)程序执行效率高,相对C# (3)迁移性差(仅支持Windows)相对QT 二、MFC程序介绍 1、MFC类库常用头…

VS2015之博大精深的MFC项目开发(一)

VS2015之博大精深的MFC项目开发&#xff08;一&#xff09; 第一章 MFC基础篇1、MFC01-2&#xff1a;Win32程序资源管理1.1 讲解MessageBox&#xff08;在windows中如何输出&#xff09;1.2 给我们的软件插入一个图标1.3 对话框程序是如何建立的&#xff08;在windows中如何输入…

简单MFC程序开发-C++反编译肉鸡养成

目录 一、需求 二、程序效果 效果1&#xff1a;鼠标左键点击&#xff0c;显示坐标 效果2&#xff1a;按下按键&#xff0c;显示键值 三、实现过程 1.创建MFC程序 2.修改添加功能 2.1 修改标题 2.2 增加鼠标消息 2.3 增加键盘消息 2.4 显示文字函数 2.5 编译生成exe 一…

MFC应用程序开发教程1

以下为本人学习笔记 原视频&#xff1a;黑马程序员MFC教程 一、基础概念 SDK&#xff1a;软件开发工具包&#xff08;Software Development Kit&#xff09;&#xff0c;第三方工具API&#xff1a;Windows擦欧总系统提供给应用程序编程的接口窗口&#xff1a;一个Windows应用…

MFC程序开发概述

MFC程序开发概述 一&#xff1a;MFC类库的产生与发展 在Microsoft推出Windows 3.0之后&#xff0c;Windows操作系统受到越来越多的人的青睐。但是不久&#xff0c;开发人员开发撰写Windows 应用程序是重复&#xff0c;厌烦的过程&#xff0c;而且效率极低。因为每一个窗口都需…

Vim撤消和重做操作

While editing text files with vim we can make some little mistakes or want to revert to the previous states. In Microsoft Word there is features rich undo and revert functions. The similar undo and revert functionalities provided by vim too. 在用vim编辑文本…

idea如何使用git指令

&#xff08;1&#xff09;、打开setting,直接搜git (2)、点一下text 如果显示成功就不用管了&#xff0c;但如果失败就要重新设置一下目录&#xff1a; &#xff08;3&#xff09;、找到自己设置gitee ssh目录&#xff1a; 这里我们是不需要用.git对.idea进行管理的&#xff…

idea操作git流程(图文教程)

idea是jetbrain的一款java编辑器&#xff0c;jetbrain全家桶的编辑器都很好用&#xff0c;接下来就以图文的方式介绍&#xff0c;idea如何操作git 1. 首先你需要在自己电脑上安装一个Git&#xff0c;安装git的流程网上应该很多了&#xff0c;这里就跳过了&#xff0c;后续操作…

IDEA中使用Git的教程

&&前期准备工作 &配置git &配置Github 1.远程创建好GitHub仓库 2.打开Terminal窗口 3.创建README.md和.gitignore文件 $touch README.md $touch .gitignore xml .gitignore内容如下: *.class package files *.war *.ear kdiff3 ignore target/ ec…

在Idea中使用Git

一.在Idea中配置Git 安装好IntelliJ IDEA后&#xff0c;如果Git安装在默认路径下&#xff0c;那么idea会自动找到git的位置&#xff0c;如果更改了Git的安 装位置则需要手动配置下Git的路径。选择File→Settings打开设置窗口&#xff0c;找到Version Control下的git选 项&…