MFC學習筆記(7)

這幾天 又跑去研究CE了—— 忽略MFC了   過幾天做下CE的筆記   不是WinCE  是Cheat.Engine

使窗口重繪三種方法:    
  1.直接調用窗口的OnPaint()  
  2.調用RedrawWindow()  
  3.發送WM_PAINT消息

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
最正確的解決方案
ls 的各位可能你們用的不是 VS2008.
由於 VS2008 sp1 引用了 BCG 的包,而 BCG 爲了方便程序員,
在註冊表中保存了窗口的大小、位置等信息,包括工具欄的相應信息。
這樣減少了程序員保存和恢復用戶上次使用過的界面的重複勞動。

而對於剛開始接觸 BCG 的人,可能不知道這些,比如 lz (我不是笑話你的意思,別誤會)
所以嘗試改變對話框大小的時候就會發現改變不了,原因就是你的程序之前至少運行過一次,
以後運行的話就會載入他上一次關閉時的大小和位置。所以給你的錯覺就是你以爲你的代碼沒有起作用。

而事實是,你的代碼是完全對的,你要做的就是刪除 BCG 爲你保存的註冊表鍵:
HKEY_CURRENT_USER/Software/[your corporation]/[your application]/Workspace
裏面 your corporation 是指在 app 類裏面 SetRegistryKey 指定的路徑;your application 就是你的應用程序名。

把這個刪掉之後,還是用你最上面的代碼,運行。OK! 

 

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
改變窗口樣式
CMainFrame::PreCreateWindow中改是在創建窗口前改
SetWindowLong是在創建窗口後改
例:SetWindowLong(m_hWnd,GWL_STYLE,WS_OVERLAPPEDWINDOW);
GetWindowLong可以在現有樣式上進行修改
例:SetWindowLong(m_hWnd,GWL_STYLE,GetWindowLong(m_hWnd,GWL_STYLE)&~WS_MAXIMIZEBOX);


改變窗口圖標 光標 背景可以編寫自己的窗口類  讓之後的窗口按照自己的窗口類來創建
可以在view類的PreCreateWindow中編寫窗口類

WNDCLASS wndcls;
wndcls.cbClsExtra=0;
wndcls.cbWndExtra=0;
wndcls.hbrBackground=(HBRUSH)GetStockObject(BLACK_BRUSH);
wndcls..hCursor=LoadCursor(NULL,IDC_HELP);
wndcls.hIcon=LoadIcon(NULL,IDI_ERROR);
wndcls.hInstance=AfxGetInstanceHandle();//返回應用程序句柄Afx開頭函數是MFC全局函數
wndcls.lpfnWndProc=::DefWindowProc;//窗口過程
wndcls.lpszClassName=L"fengjiang";
wndcls.lpszMenuName=NULL;
wndcls.style=CS_HREDRAW|CS_VREDRAW;

RegisterClass(&wndcls);//註冊窗口類

cs.lpszClass="fengjiang";//把窗口類改成自己定義的

注意view是覆蓋在框架窗口上的  如果要修改圖標 需要在框架窗口上編寫窗口類  如果是在view類上的光標和背景需要在view類中編寫  
自定義窗口類的方法很是麻煩下面我們用一個全局函數 搞定之
在框架類的PreCreateWindow中可以用它改圖標
在view類中可以用它改背景和光標
AfxRegisterWndClass
框架類中:
cs.lpszClass=AfxRegisterWndClass(CS_HREDRAW|CS_VREDRAW,0,0,LoadIcon(NULL,IDI_WARNING));

view類中:
cs.lpszClaee=AfxRegisterWndClass(CS_HREDRAW|CS_VREDRAW,LoadCursor(NULL,IDC_CROSS),(HBRUSH)GetStockObject(BLACK_BRUSH),0);

上述方法是在創建窗口前改變圖標光標等

有一個全局函數可以在創建窗口後修改
SetClassLong
例:SetClassLong(m_hWnd,GCL_HCURSOR,(LONG)LoadCursor(NULL,IDC_HELP));

圖標動畫效果 
用SetClassLong每隔一段時間換一下圖標   用SetTimer實現
添加WM_TIMER消息響應函數 
*把一個值始終控制在一個範圍內  最好的方法是取模
例如:index=++index%3;

創建自己的工具欄
(1)
1.Create a toolbar resource.

2.Construct the CToolBar object.

3.Call the Create (or CreateEx) function to create the Windows toolbar and attach it to the CToolBar object.

4.Call LoadToolBar to load the toolbar resource.

按照上述方法操作下來 發生了錯誤   我是廢了不少心思   才知道 是因爲VS2008中  創建這個工具欄  用的是CMFCToolBar   CToolBar適用於VC6++ 

我把VS2008下實現的代碼寫下來
CMFCToolBar m_mybar;

。。。。。。。

 if (!m_mybar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) ||
  !m_mybar.LoadToolBar(IDR_TOOLBAR1))
 {
  TRACE0("未能創建工具欄/n");
  return -1;      // 未能創建
 }
 m_mybar.EnableDocking(CBRS_ALIGN_ANY);//可停靠
 DockPane(&m_mybar);  //停靠在主框架窗口上


另外
////////////////////////////////////////////////////////
如果定義的是CToolBar類,如:CToolBar m_wndToolBar;

當需要顯示或隱藏工具欄是可以使用showcontrolbar(&m_wndToolBar,TRUE/FALSE, FALSE)來實現。然後一開始定義的是CMFCToolBar類時,如:CMFCToolBar m_wndToolBar;不能用showcontrolbar實現隱藏和顯示,因爲showcontrolbar()的第一個參數是CToolBar類型。這時可以調用ShowWindow(SW_SHOW/SW_HIDE)實現:m_wndToolBar.ShowWindow(SW_SHOW/SW_HIDE)。

 if(m_mybar.IsWindowVisible())
 {
  m_mybar.ShowWindow(SW_HIDE);
 }
 else
 {
  m_mybar.ShowWindow(SW_SHOW);
 }
 RecalcLayout();  //恢復原樣
 DockPane(&m_mybar); //停靠工具欄
在上述基礎上如果要給菜單項做複選  首先 給菜單項增加一個UPDATE_COMMAND_UI的命令相應   然後進去pCmdUI->SetCheck(m_mybar.IsWindowVisible());
////////////////////////////////////////////////////////

*由於無法適應VS2008 帶來的改變  我在學MFC當中遇到了不少麻煩  這個筆記做完之後  準備專門把我在編程中遇到的VS2008與VC6++的幾個不同之處總結一下   也算是造福人類了 汗——

工具欄的ID和菜單項裏對應功能的項的ID是一樣的  直接在菜單裏相應功能就可以了

創建狀態欄窗格
首先創建string table項
然後在static UINT indicators[]中添加string table項ID

////////////////////////////////////////////////////////
 CTime t = CTime::GetCurrentTime();  
 CString str=t.Format(L"%H:%M:%S");
 CClientDC dc(this);
 CSize sz=dc.GetTextExtent(str);
 m_wndStatusBar.SetPaneInfo(1,IDS_TIMER,SBPS_NORMAL,sz.cx); //設置窗格寬度
 m_wndStatusBar.SetPaneText(1,str);
 CFrameWndEx::OnTimer(nIDEvent);
////////////////////////////////////////////////////////

////////////////////////////////////////////////////////
 CRect rect;
 m_wndStatusBar.GetItemRect(2,&rect);
 if(!m_myCtrl.m_hWnd)
 {
  m_myCtrl.Create(WS_CHILD|WS_VISIBLE|PBS_SMOOTH,rect, &m_wndStatusBar, 123);
 }
 else
 {
  m_myCtrl.MoveWindow(rect);
 }
 m_myCtrl.SetPos(50);

讓進度前進  有SetpIt和SetRange
////////////////////////////////////////////////////////


任何自定義消息
首先在頭文件中定義
#define  UM_MY     WM_USER+1 //系統消息ID都在WM_USER之下
然後在頭文件中聲明消息響應函數
afx_msg void OnMy();
之後建立消息映射  將消息與消息響應函數關聯起來
ON_MESSAGE(UM_MY,OnMy)
最後寫消息響應函數的實現部分

SendMessage是直接把消息發給消息響應函數  執行後然後再返回
PostMessage是把消息放到消息隊列中  就立即返回

在狀態欄上 顯示鼠標座標
///////////////////////////////////////////////////////////
void CStyleView::OnMouseMove(UINT nFlags, CPoint point)
{
 CString str;
 str.Format(L"x=%d,y=%d",point.x,point.y);
 ((CMainFrame *)GetParent())->m_wndStatusBar.SetWindowText(str);
//((CMainFrame *)GetParent())->SetMessageText(str);
//((CMainFrame *)GetParent())->GetMessageBar()->SetWindowText(str);

 CView::OnMouseMove(nFlags, point);
}
///////////////////////////////////////////////////////////

程序啓動畫面
VS2008中貌似無法插入Splash Screen組件
我準備嘗試用AnimateWindow API自己來做
待續

發佈了15 篇原創文章 · 獲贊 20 · 訪問量 29萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章