______________________________废话
一直用的是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
.
.
.