______________________________廢話
一直用的是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
.
.
.