您的位置:首页 > 其它

VS2010环境 MFC 桌面精灵 制作

2010-12-02 21:15 435 查看
______________________________废话

一直用的是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

.

.

.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: