天天看點

VS2010環境 MFC 桌面精靈 制作

______________________________廢話

    一直用的是VC6,電腦裡面的VS2008玩過一次,玩暈了,在操作上和VC6相比,實在是相差好遠,感覺有點難,

    正好VS2010出了,說是VC6的類向導又回來了,于是就裝了一個,- - 那天裝了N次裝上去有很多問題,于是就一直放着沒管,

    後來又一天,就想着重新裝一次吧,然後很謹慎的又裝了一次,RP爆發 - - 安裝過程居然沒有重新開機,而且MSDN也是一次就搞定 哈哈 小高興

    後來就準備寫一個程式,也是我一直想寫的 桌面精靈 ,也算是 我邊學VS2010的使用,邊學這個程式的制作吧 呵呵

    恩恩 從VC6 過度到 VS2010 基本還算順利 習慣了2010的那麼慢了 - - 有些設定網上面都有.然後就是因個人愛好功能删删減減的~我就不多說了

______________________________說明

1.  如果大家還是想用VC6來寫其實也無妨看看我自己整理的東西,畢竟基本的順序 函數 之類的都差不多

2.  參考了網上面的大話西遊的那個的代碼,從裡面學到很多東西,我也是删減了裡面較為複雜的功能,然後做的稍微簡單一點的

     待會和我的一起傳到CSDN上面,貼下位址....

______________________________正題

______主要步驟______

1. 建立基于對話框的程式

.

.

2.CWinApp 的 子類源檔案 的 InitInstance()中

    從CWnd 派生出一個自己的視窗類 暫命名為 CHappy

   // CHappy *pWnd=new CHappy;

.

.

3. CWinApp 的 子類源檔案 的 InitInstance()中

    定義一個 CHappy 視窗類 的對象指針 并賦給 m_pMainWnd

    (原先是将對話框的對象指針賦給 m_pMainWnd 的)

   // m_pMainWnd=pWnd;

.

.

4.接着 繼續調用Happy中[自定義]的函數CHappy::CreateMyWnd() , 建立視窗

  CHappy::CreateMyWnd() 主要負責 建立自己的視窗, 位圖關聯位圖對象, 獲得視窗的width 和 height , 設定定時器等等

  CHappy::CreateMyWnd() 中

                     調用[自定義]的    CHappy::SetWndRgn(void);  主要負責去掉圖檔的白色 變成透明顔色 儲存幾張圖檔的rgn

                     再調用[自定義]的 CHappy::ChangeWnd(void);  主要負責改變目前視窗的樣子 ( 利用函數 SetWindowRgn(); )

                     再調用 SetTimer(); 設定定時器 以變換圖檔

.

.

5. 接着 繼續調用 ShowWindow(SW_SHOW) 顯示視窗

    之後傳回 TRUE 繼續消息循環 不退出

.

.

CHappy類裡面負責視窗的建立,圖檔的變換等等等工作

再從CDialogEx派生一個對話框類,用于設定圖檔變換的時間間隔,自定義滑鼠右鍵菜單等~

.

.

.

.

下面是CDeskTopApp::InitInstance() 函數

BOOL CDeskTopApp::InitInstance()

{

// 如果一個運作在 Windows XP 上的應用程式清單指定要

// 使用 ComCtl32.dll 版本 6 或更高版本來啟用可視化方式,

//則需要 InitCommonControlsEx()。否則,将無法建立視窗。

INITCOMMONCONTROLSEX InitCtrls;

InitCtrls.dwSize = sizeof(InitCtrls);

// 将它設定為包括所有要在應用程式中使用的

// 公共控件類。

InitCtrls.dwICC = ICC_WIN95_CLASSES;

InitCommonControlsEx(&InitCtrls);

CWinApp::InitInstance();

// 建立 shell 管理器,以防對話框包含

// 任何 shell 樹視圖控件或 shell 清單視圖控件。

///CShellManager *pShellManager = new CShellManager;

CHappy *pWnd=new CHappy;

m_pMainWnd=pWnd;

pWnd->CreateMyWnd();

pWnd->CenterWindow();

pWnd->ShowWindow(SW_SHOW);

return TRUE; //繼續消息循環?!

// 标準初始化

// 如果未使用這些功能并希望減小

// 最終可執行檔案的大小,則應移除下列

// 不需要的特定初始化例程

// 更改用于存儲設定的系統資料庫項

// TODO: 應适當修改該字元串,

// 例如修改為公司或組織名

///原來是基于對話框的程式!!!

/*

SetRegistryKey(_T("應用程式向導生成的本地應用程式"));

CDeskTopDlg dlg;

m_pMainWnd = &dlg;

INT_PTR nResponse = dlg.DoModal();

if (nResponse == IDOK)

{

// TODO: 在此放置處理何時用

// “确定”來關閉對話框的代碼

}

else if (nResponse == IDCANCEL)

{

// TODO: 在此放置處理何時用

// “取消”來關閉對話框的代碼

}

// 删除上面建立的 shell 管理器。

if (pShellManager != NULL)

{

delete pShellManager;

}

// 由于對話框已關閉,是以将傳回 FALSE 以便退出應用程式,

// 而不是啟動應用程式的消息泵。

return FALSE;

*/

}

主要步驟在上面已經說明

__因為我程式中稍微難點的代碼幾乎都已經配上了注釋,是以我就撿我覺得有價值的代碼貼上吧__

1.CHappy::OnCreate 建立 主要負責右鍵菜單的初始化 以及ini檔案的寫入讀出工作

  a. GetPrivateProfileString()

  b. WritePrivateProfileString()

int CHappy::OnCreate(LPCREATESTRUCT lpCreateStruct)

{

if (CWnd::OnCreate(lpCreateStruct) == -1)

return -1;

// TODO: 在此添加您專用的建立代碼

//設定程式的圖示

SetClassLong( m_hWnd , GCL_HICON , (LONG32)LoadIcon( AfxGetInstanceHandle() , MAKEINTRESOURCE( IDI_ICON1) ) );

//菜單名賦預設值

m_strCap[0] = INI_MENU0 ;

m_strCap[1] = INI_MENU1 ;

m_strCap[2] = INI_MENU2 ;

m_strCap[3] = INI_MENU3 ;

m_strCap[4] = INI_MENU4 ;

//菜單名對應的位址(網址)賦預設值

m_strADD[0] = INI_ADD0 ;

m_strADD[1] = INI_ADD1 ;

m_strADD[2] = INI_ADD2 ;

m_strADD[3] = INI_ADD3 ;

m_strADD[4] = INI_ADD4 ;

// 段名 鍵名(菜單名) 串名(對應位址)

CString strSection , strKeyMenu , strKeyADD ;

//如果 INI_PATH 路徑下有ini配置檔案,則直接從該檔案中讀取資訊 ,

//如果沒有, 則使用上面預設的值來配置程式,并建立該配置資訊

for (int i = 0; i < MENU_NUM ; i++) //MENU_NUM:菜單個數

{

strSection.Format( _T( "菜單%d" ) , i ) ;

strKeyMenu.Format( _T( "菜單名%d" ) , i ) ;

strKeyADD.Format( _T( "位址%d" ) , i ) ;

GetPrivateProfileString( strSection , strKeyMenu , m_strCap[ i ] , m_strCap[ i ].GetBuffer(100) , 100 , _T( INI_PATH ) ) ;

GetPrivateProfileString( strSection , strKeyADD , m_strADD[ i ] , m_strADD[ i ].GetBuffer(100) , 100 , _T( INI_PATH ) ) ;

/* Retrieves a string from the specified section in an initialization file.

DWORD WINAPI GetPrivateProfileString(

__in LPCTSTR lpAppName, //段名

__in LPCTSTR lpKeyName, //鍵名

__in LPCTSTR lpDefault, //預設值(如果沒有該ini檔案, 或沒有讀出該資訊 ,則用這個預設值 )

__out LPTSTR lpReturnedString, //接收傳回的字元串

__in DWORD nSize, //傳回字元串的大小

__in LPCTSTR lpFileName //ini檔案的存儲路徑

);

*/

//如果沒有ini檔案, 也就是使用的預設的值, 則建立檔案

WritePrivateProfileString( strSection , strKeyMenu , m_strCap[ i ] , _T( INI_PATH ) ) ;

WritePrivateProfileString( strSection , strKeyADD , m_strADD[ i ] , _T( INI_PATH ) ) ;

}

return 0;

}

.

.

.

.

.

2.CHappy::SetWndRgn(void); 主要負責去掉圖檔的白色 變成透明顔色 儲存幾張圖檔的rgn

   a.GetPixel(x , y); 得到 坐标(x , y ) 的 像素值

   b.CreateRectRgn(); 建立矩形區域

   c.CombineRgn() ; 合并區域,關鍵在第三個參數上

void CHappy::SetWndRgn(void)

{

for ( int n = 0 ; n < m_nPicNum ; n++ )

{

// m_bitmap[ n ].DeleteObject(); //- - 要記得先删除關聯的對象

// m_bitmap[ n ].LoadBitmap( IDB_BITMAP1 + n ); //位圖對象關聯位圖資源

CClientDC dc(this);

CDC dcCompatible;

dcCompatible.CreateCompatibleDC( &dc );

//用已有dc建立相容dc-->dcCompatible, 并關聯位圖資源

CBitmap * pBmp = dcCompatible.SelectObject( &m_bitmap[ n ] );

COLORREF colMask = dcCompatible.GetPixel( 0 , 0 ) ;

//獲得( 0 , 0)坐标的像素值 (預設是将白色全部去掉,顯示透明,具體看下面)

CRgn rgn;

m_rgn[ n ].DeleteObject();

m_rgn[ n ].CreateRectRgn( 0 , 0 , m_nBmpWidth , m_nBmpHeight );

//建立圖檔那麼大小的

int x , y ;

for ( y = 0 ; y< m_nBmpHeight ; y++ )

{

for ( x = 0 ; x<m_nBmpWidth ; x++ )

{

if ( dcCompatible.GetPixel( x , y ) == colMask ) //獲得目前坐标的像素顔色 , 如果相等 即 如果是白色

{ //将白色去掉 變成透明

rgn.CreateRectRgn( x , y , x + 1 , y + 1);

m_rgn[ n ].CombineRgn( &m_rgn[ n ] , &rgn , RGN_XOR ); //RGN_XOR 交操作 但是去除重疊的顔色

rgn.DeleteObject(); // 去掉了相同的白色部分

}

}

}

}

}

.

.

.

.

.

3.CHappy::ChangeWnd(void)  主要負責改變目前視窗的樣子 利用函數 SetWindowRgn()

   a. CopyRgn()  避免系統去除了自定義的rgn!!

void CHappy::ChangeWnd(void)

{

if ( m_nPic >= m_nPicNum -1 )

{

m_nPic = -1;

}

m_nPic++;

CRgn TempRgn;

TempRgn.CreateRectRgn( 0 , 0 , 0 , 0 ) ; //********************************

TempRgn.CopyRgn(&m_rgn[ m_nPic ] ) ; //避免系統去除了自定義的rgn

SetWindowRgn((HRGN)TempRgn , true ) ; //使用臨時rgn來設定目前視窗!!!!!

/* Copies the region defined by pRgnSrc into the CRgn object.

int CopyRgn(

CRgn* pRgnSrc

);

*/

Invalidate(); //重繪 即要調用下面的 OnEraseBkgnd() 函數

}

.

.

.

.

.

4.CHappy::OnLButtonDown(UINT nFlags, CPoint point)  滑鼠左鍵點選

   a.PostMessage(WM_NCLBUTTONDOWN, HTCAPTION , MAKELPARAM( point.x, point.y) );

      客戶區點選 發送非客戶區點選的消息 實作非标題欄拖動視窗

void CHappy::OnLButtonDown(UINT nFlags, CPoint point)

{

// TODO: 在此添加消息處理程式代碼和/或調用預設值

PostMessage(WM_NCLBUTTONDOWN, HTCAPTION , MAKELPARAM( point.x, point.y) );

//客戶區點選 發送非客戶區點選的消息 實作非标題欄拖動視窗

// - - 糾結 這消息機制

CWnd::OnLButtonDown(nFlags, point);

}

.

.

.

.

.

5.void CHappy::OnRButtonDown(UINT nFlags, CPoint point)

     a.ModifyMenu(); 修改菜單 實作自定義的菜單

void CHappy::OnRButtonDown(UINT nFlags, CPoint point)

{

// TODO: 在此添加消息處理程式代碼和/或調用預設值

CMenu PopMenu;

PopMenu.LoadMenu( IDR_POPUPMENU ) ;

CMenu * pPopMenu = PopMenu.GetSubMenu( 0 ) ;

//獲得子菜單指針 根據使用者設定 依次修改菜單項的内容

for (int i = 0; i < MENU_NUM ; i++)

{

pPopMenu->ModifyMenu(

ID_POPUPMENU1 + i ,

MF_BYCOMMAND | MF_POPUP ,

ID_POPUPMENU1 + i ,

m_strCap[ i ] ) ;

}

/*Changes an existing menu item at the position specified by nPosition.

BOOL ModifyMenu(

UINT nPosition,

UINT nFlags,

UINT_PTR nIDNewItem = 0,

LPCTSTR lpszNewItem = NULL

) ;

*/

ClientToScreen( &point ) ;

//轉換成螢幕坐标

pPopMenu->TrackPopupMenu( TPM_LEFTALIGN | TPM_RIGHTALIGN , point.x , point.y , this );

//彈出菜單

PopMenu.Detach() ;

//局部菜單對象 需要detach()消除關聯(孫鑫老師視訊教程)

CWnd::OnRButtonDown(nFlags, point);

}

.

.

.

.

.

6.CHappy::OnPopupmenuSelf() ; 單擊[自定義]菜單項 彈出對話框

   這個裡面沒有陌生的函數方法等,但是很需要注意~

   主要的判斷就是

if (點選的是[确定])

{

}

else if (點選的是 [進階]--[确定] )

{

}

void CHappy::OnPopupmenuSelf()

{

CDlgSelfdef dlg; //***** 别忘了 dlg這個對象的生存周期

for (int i = 0; i < MENU_NUM ; i++)

{

dlg.m_strCap[ i ] = m_strCap[ i ];

dlg.m_strADD[ i ] = m_strADD[ i ];

dlg.m_nTime = m_nTime;

//将happy.cpp裡面的成員變量指派到對話框的成員變量中

//并在對話框中 将值賦到控件中

//SetDlgItemText() 這裡不知道為啥不能用 很郁悶 糾結了我N久 聽說是句柄指針的問題

}

//如果對話框上單擊的是 [确定] 則調用

//當然 會先調用對話框裡面重載的函數 OnBnClickedOk() 再執行後面的操作

int nResult = dlg.DoModal() ;

if ( IDOK == nResult ) // 如果按下的是 OK

{

for (int i = 0; i < MENU_NUM ; i++)

{

//針對 如果對話框控件中的字元串被修改了 将串值儲存

CString strSection , strKeyMenu , strKeyADD ,strVal ;

m_strCap[ i ] = dlg.m_strCap[ i ] ;

m_strADD[ i ] = dlg.m_strADD[ i ] ;

strSection.Format( _T( "菜單%d" ) , i ) ;

strKeyMenu.Format( _T( "菜單名%d" ) , i ) ;

strKeyADD.Format( _T( "位址%d" ) , i ) ;

WritePrivateProfileString( strSection , strKeyMenu , m_strCap[ i ] , _T( INI_PATH ) ) ;

WritePrivateProfileString( strSection , strKeyADD , m_strADD[ i ] , _T( INI_PATH ) ) ;

//及時儲存到ini檔案中

m_nTime = dlg.m_nTime ;

//重設時間

KillTimer( 1 );

SetTimer( 1 , m_nTime , NULL ) ;

}

}

else if ( IDHI == nResult ) // 如果 按下的是 進階

{

m_nPic = 0; //目前圖檔是 第0号

m_nPicNum = 0; //目前有 0 張圖檔

for ( int i = 0; i < PIC_NUM ; i++) //最大儲存4張圖檔

{

//m_strADDpic[ i ] = _T(" ") ;

m_strADDpic[ i ] = dlg.m_strADDpic[ i ] ;

if ( m_strADDpic[ i ] == _T("") ) //如果沒有導入完4張圖檔 就隻用前面的幾張來實作

{

break;

}

m_nPicNum++ ; //目前使用的圖檔數量

}

m_nBmpWidth = 0;

m_nBmpHeight = 0;

for ( int n = 0 ; n < m_nPicNum ; n++ )

{

//取消關聯 位圖對象

m_bitmap[ n ].DeleteObject();

//取消關聯 位圖句柄

m_bitmap[ n ].Detach();

HBITMAP hbitmap=(HBITMAP)::LoadImage( NULL , m_strADDpic[ n ] , IMAGE_BITMAP , 0 , 0 , LR_LOADFROMFILE ) ;

m_bitmap[ n ].Attach(hbitmap);

BITMAP bmpInfo;

m_bitmap[ n ].GetBitmap( &bmpInfo );

//儲存最大一張位圖的 寬 高

if ( bmpInfo.bmWidth > m_nBmpWidth ) m_nBmpWidth= bmpInfo.bmWidth ;

if ( bmpInfo.bmHeight > m_nBmpHeight ) m_nBmpHeight = bmpInfo.bmHeight ;

}

// 如果 一張圖檔都沒有導入~

//提示對話框

//并使用預設的4位圖來實作程式

if ( 0 == m_nPicNum )

{

MessageBox( _T( "請選擇好圖檔路徑!" ) , _T( " 遙遠 " ) ) ;

m_nBmpWidth = 0;

m_nBmpHeight = 0;

for ( int i = 0 ; i < PIC_NUM ; i++ )

{

m_bitmap[ i ].DeleteObject();

m_bitmap[ i ].Detach();

m_bitmap[ i ].LoadBitmap( IDB_BITMAP1 + i ) ;

BITMAP bmpInfo;

m_bitmap[ i ].GetBitmap( &bmpInfo );

//儲存最大一張位圖的 寬 高

if ( bmpInfo.bmWidth > m_nBmpWidth ) m_nBmpWidth= bmpInfo.bmWidth ;

if ( bmpInfo.bmHeight > m_nBmpHeight ) m_nBmpHeight = bmpInfo.bmHeight ;

}

m_nPicNum = PIC_NUM ; //預設有4張

}

//重新設定視窗位置 (改變視窗的大小)

SetWindowPos( NULL , 0 ,0 ,m_nBmpWidth , m_nBmpHeight ,SWP_NOMOVE | SWP_NOZORDER);

SetWndRgn(); //調用下面的函數 建立圖檔區域

ChangeWnd();

Invalidate();

//SetWindowPos( NULL , 0 ,0 ,50,50 ,SWP_NOMOVE | SWP_NOZORDER);

//MessageBox(NULL);

}

}

.

.

.

.

.

7.void CHappy::OnPopupmenu1()

    a.ShellExecute() 調用浏覽器 打開網頁位址

{

// TODO: 在此添加指令處理程式代碼

ShellExecute( NULL , _T( "open" ) , m_strADD[ 0 ] , NULL , NULL , SW_MAXIMIZE ) ;

/* Performs an operation on a specified file.

HINSTANCE ShellExecute(

HWND hwnd, //This value can be NULL if the operation is not associated with a window.

LPCTSTR lpOperation, //specifies the action to be performed.

LPCTSTR lpFile,

LPCTSTR lpParameters,

LPCTSTR lpDirectory,

INT nShowCmd

);

*/

}

.

.

.

.

.

8.然後就是 自定義對話框裡面與主對話框裡面的資料的交換的工作了

.

.(略)

.

.

.

.

恩恩  先就這樣吧~

程式下載下傳位址:

 http://download.csdn.net/source/2877662

 .

.

.

繼續閱讀