VC++ 常用编程技巧总结

VC++6.0的使用以及编程技巧整理



1、MDI子窗口一启动就最大化   
  BOOL   CChildFrame::PreCreateWindow(CREATESTRUCT&   cs)  
  {  
  //   TODO:   Modify   the   Window   class   or   styles   here   by   modifying  
  //     the   CREATESTRUCT   cs  
  cs.style=WS_CHILD   |   WS_VISIBLE   |   WS_OVERLAPPEDWINDOW|WS_MAXIMIZE;  
  if(   !CMDIChildWnd::PreCreateWindow(cs)   )  
  return   FALSE;  
   
  return   TRUE;  
  }    
 
2、主窗口最大化:  
          在   InitStance   函数中设定   m_nCmdShow的取值.   
           m_nCmdShow   =   SW_SHOWMAXIMIZED;    
    if   (!ProcessShellCommand(cmdInfo))  
      return   FALSE;   


  MDI窗口:  
          重载   MDI   Window   的PreCreateWindow函  
  数,设置WS_MAXIMIZE  
  文档一生成就最大化:  
          在视类重载的OnInitUpdate成员函数中加上:    
          CMDIChildWnd   *pWnd=(CMDIChildWnd   *)GetParentFrame();    
          pWnd->MDIMaximize();
 3、设置多文档的标题
设置标题在如下两个函数
BOOL CTOLLGATE_OF_CITYDoc::OnNewDocument()
{
if (!CDocument::OnNewDocument())
return FALSE;
SetTitle ("你的文档名");
return TRUE;
}
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
if( !CFrameWnd::PreCreateWindow(cs) )
return FALSE;
m_strTitle ="标题";
return TRUE;
}
 4 mdi怎样可以使启动程序时不打开子窗口?
在应用程序的初始化函数InitInstance中的  
  CcommandLineInfo   cmdInfo;  
  语句后加入:  
  cmdInfo.m_nShellCommand=CCommandLineInfo::FileNothing;     (要尤氲拇耄? 
   
  ParseCommandLine(cmdInfo);     (该句已有,不用加)  
  即可。  
  是CWinApp类中的函数
5 怎样单击窗体任何位置就可移动窗体
加上左键按下消息  
  void   CXXXDlg::OnLButtonDown(UINT   nFlags,   CPoint   point)    
  {   
    //加上下面这句话  
  PostMessage(WM_NCLBUTTONDOWN,HTCAPTION,MAKELPARAM(point.x,point.y));     
  CDialog::OnLButtonDown(nFlags,   point);   
  
  }  
6 VC下用ADO连接ORACLE数据库
Oracle公司提供的连接方式:  
  使用标准安全级别:  
  strConnect   =   _T("Provider=OraOLEDB.Oracle;Data   Source=MyOracleDB;User   Id=myUsername;Password=myPassword;");  
  使用信任连接  
  1.strConnect   =   _T("Provider=OraOLEDB.Oracle;Data   Source=MyOracleDB;User   Id=/;Password=;");   UID为'/'  
  2.strConnect   =   _T("Provider=OraOLEDB.Oracle;Data   Source=MyOracleDB;OSAuthent=1;");使用OSAuthent=1  
  对于连接字符串可以参考以下网页:   http://msdn.microsoft.com/library/default.asp?url=/library/en-us/ado270/htm/mdreforacleprovspec.asp?frame=true  
  http://download-west.oracle.com/otndoc/oracle9i/901_doc/win.901/a90171/using.htm  
  ===>ODBC   配置数据源  
  strConnect   =   _T("DSN=ADOTest");
 
编程小技巧
http://hi.baidu.com/original/blog/item/c0f7e850e9b6545f1138c275.html
 
去掉单文档的“无标题”
  if( !CFrameWnd::PreCreateWindow(cs) )
  return FALSE;
 // TODO: Modify the Window class or styles here by modifying
 //  the CREATESTRUCT cs
 cs.style   &=   ~FWS_ADDTOTITLE;
 VC编程做个超级链接的文本按钮
http://sjtu.blog.sohu.com/71163647.html
VC下利用ADO连接Access数据库 
http://blog.csdn.net/pixy0m0/archive/2007/04/17/1568224.aspx
SQL语句VC中的分行 
pcmd->CommandText   =   "SELECT   *               \  
  FROM   OrderTable   WHERE   OrderID   =   ?";
各种类型转换


常用数据类型使用转换详解
http://sjtu.blog.sohu.com/77555070.html
CString 转 int  atoi
CString to double
Cstring与double char 的转换
http://blog.csdn.net/paobo/archive/2007/05/15/1610032.aspx
四舍五入  int(num+0.5)   %.2f
查询Excel表要用$结尾不然找不到  select *  FROM [Stockpool$]
数据库表中字段含有括号的话 用中括号括起来表示特殊字符 例如 [EPS(T+1)]
CListCtrl使用技巧    http://sjtu.blog.sohu.com/72301523.html
打开网页文件
ShellExecute(hWnd,"open","ieexplorer",CString("file://")+filename   +   CString("#a1"),   NULL,SW_SHOWNORMAL);   
深入浅出ShellExecute
http://sjtu.blog.sohu.com/72316353.html
 Excel中时间字段的查询: Time>#2007-12-03 00:00:00#
 VC窗口自由的调整大小的实现
http://www.codeproject.com/dialog/easysize.asp
http://www.xfbbs.com/ArticleShow/85/Article_Show_72223.html
 
用VC++获取系统时间几种方法 
CTime:
%Y%m%d%h%M%S 年月日 时分秒
就用CTime::GetDayOfWeek()   or   COleDateTime::::GetDayOfWeek()啊,他返回一个int,如果返回值是1就说明是星期天,如果是2表示星期一...如果是7表示星期六(每个星期的第一天是星期天) 
A:
1 使用time_t time( time_t * timer )    精确到秒
  计算时间差使用double difftime( time_t timer1, time_t timer0 )
2 使用clock_t clock() 得到的是CPU时间    精确到1/CLOCKS_PER_SEC秒
3 使用DWORD GetTickCount() 得到的是系统运行的时间 精确到毫秒
4 如果使用MFC的CTime类,可以用CTime::GetCurrentTime() 精确到秒
5 要获取高精度时间,可以使用
    BOOL QueryPerformanceFrequency(LARGE_INTEGER *lpFrequency)获取系统的计数器的频率
    BOOL QueryPerformanceCounter(LARGE_INTEGER *lpPerformanceCount)获取计数器的值
    然后用两次计数器的差除以Frequency就得到时间。
6 还有David的文章中提到的方法:
    Multimedia Timer Functions
    The following functions are used with multimedia timers.
    timeBeginPeriod/timeEndPeriod/timeGetDevCaps/timeGetSystemTime
    timeGetTime/timeKillEvent/TimeProc/timeSetEvent  精度很高 
Q:GetTickCount()函数,说是毫秒记数,是真的吗,还是精确到55毫秒?
A:
GetTickCount()和GetCurrentTime()都只精确到55ms(1个tick就是55ms)。如果要精确到毫秒,应该使用timeGetTime函数或QueryPerformanceCounter函数。具体例子可以参考QA001022 "VC++中使用高精度定时器"、QA001813 "如何在Windows实现准确的定时"和QA004842 "timeGetTime函数延时不准"。
Q:vc++怎样获取系统时间,返回值是什么类型的变量呢? 
GetSystemTime返回的是格林威志标准时间
GetLocalTime,和上面用法一样,返回的是你所在地区的时间,中国返回的是北京时间
 
VOID GetSystemTime(
LPSYSTEMTIME lpSystemTime // address of system time structure
);
函数就可以获得了,其中LPSYSTEMTIME 是个结构体
含:年,月,日,周几,小时,分,秒,毫秒。
 
Disable一个控件:GetDlgItem(IDC_BUTTON1)->EnableWindow(FALSE);
 
VC中如何发布Release版本 工具栏上点右键,选择编译,将编译win32debug改为win32 Release即可。如果需要调试的话,还需要再改回来方可
 
VC程序可以再其它机子上运行:
你的目标程序需要动态链接库文件的支持,    
  把程序中用到的DLL文件放到程序的目录下就可以运行了。
project->setting->General->下拉框中选择"Use   MFC   in   a   Static   Library”
 
 
第一:private, public, protected 访问标号的访问范围。
private:只能由1.该类中的函数、2.其友元函数访问。
不能被任何其他访问,该类的对象也不能访问。


protected:可以被1.该类中的函数、2.子类的函数、以及3.其友元函数访问。
但不能被该类的对象访问。


public:可以被1.该类中的函数、2.子类的函数、3.其友元函数访问,也可以由4.该类的对象访问。
 
注:友元函数包括3种:设为友元的普通的非成员函数;设为友元的其他类的成员函数;设为友元类中的所有成员函数。


第二:类的继承后方法属性变化。
private 属性不能够被继承。
使用private继承,父类的protected和public属性在子类中变为private;
使用protected继承,父类的protected和public属性在子类中变为protected;
使用public继承,父类中的protected和public属性不发生改变; 
 
如下所示: 
                                 public:            protected:       private:
public继承             public             protected        不可用 
protected继承       protected       protected        不可用 
private继承            private           private             不可用 


protected继承和private继承能降低访问权限。
 
 CTime COleDateTime的常用操作和比较
百分号的表示
用%%表示% ,或者CStrng   str;  
  str.format("select   *   from   Name   where   address   like   %sabc%s","%","%");
viewform.cpp line 69 错误: 应该把dialog改为child。
 
取消所有断点 edit->breakpoints->remove all 或者 Ctrl+Shift+F9
 
设置checkBox属性为选中  ((CButton   *)GetDlgItem(IDC_CHECK1+i))->SetCheck(1);  
判断是否选中  if(IsDlgButtonChecked(IDC_SEX1)) 
取得活动视图和主框架
  CMainFrame   *pMainFrame=(CMainFrame   *)AfxGetMainWnd();  
  CSRSFormView   * pView  =(CSRSFormView *)pMainFrame->GetActiveView();
关于missing ';' before identifier 'A'  两个文件的相互引用引起的...
 
VC中看不到类:删除clw文件 重新建立
 
获取控件的中心:GetDlgItem(IDC_SEARCH1)->GetWindowRect(&rc); rc.CenterPoint()
 
SendMessage 传递多个变量:
        tObj *fi=new tObj;
        fi->iItem=idx;
        fi->iFolder=iSelFolder;
   GetOwner()->SendMessage(WM_OUTBAR_NOTIFY, NM_OB_ITEMCLICK, (UINT)fi);
那边接收到后再用(tObj*)转换回来
 
问题: 请问何时用UpdateData(false),何时用UpdateData(true)呢?
答案:当你使用了ClassWizard建立了控件和变量之间的联系后:当你修改了变量的值,而希望对话框控件更新显示,就应该在修改变量后调用UpdateData(FALSE);如果你希望知道用户在对话框中到底输入了什么,就应该在访问变量前调用UpdateData(TRUE)。
设置控件标题   GetDlgItem(IDC_GetCapProfit)->SetWindowText("全部显示");
 
DateTime change事件被执行二次的改进:
 static   BOOL   bOK=TRUE;  
#if   1//判断是否有CMonthCalCtrl,若有会发送两次Change,截第二次即可  
 CDateTimeCtrl*   pCtrl   =   (CDateTimeCtrl*)   GetDlgItem(IDC_DATESELECTED);  
 ASSERT(pCtrl   !=   NULL);  
 CMonthCalCtrl*   pMoCalCtrl   =   pCtrl->GetMonthCalCtrl();  
 if(pMoCalCtrl   !=   NULL)  
        bOK   =   !bOK;  
#endif  
 if(bOK)  
  AfxMessageBox("");  
  *pResult   =   0;    
无模式对话框:Cdlg dlg; dlg.Create(IDD_DIALOG1,this); dlg.ShowWindow(SW_SHOW);
先为对话框加上2个radio button,分别是Radio1和Radio2。
问题1:如何让Radio1或者Radio2默认选上?如何知道哪个被选上了?


关键是选上,“默认”只要放在OnInitDialog()即可。三种方法可以让它选上,
第一种:
((CButton *)GetDlgItem(IDC_RADIO1))->SetCheck(TRUE);//选上
((CButton *)GetDlgItem(IDC_RADIO1))->SetCheck(FALSE);//不选上
((CButton *)GetDlgItem(IDC_RADIO1))->GetCheck();返回1表示选上,0表示没选上
第二种:
关联一个congtrol型变量(子类化),好ctrl+W(即打开classwizard),点开 Member Variables,咦?怎么没有IDC_RADIO1这个ID?原来是没有分组。因为radio button通常都是成组使用的,在一组里面是互斥的。取消,回到对话框资源面板,右键Radio1查看属性把Group选上,那么,Radio1和Radio2就是一组了(怎么知道他们是一组的?后面说)。此时,就可以为Radio1增加一congtrol型变量m_ctrlRadio1了。如下:
m_ctrlRadio1.SetCheck(TRUE);
同样可以使用GetCheck()获取状态。
第三种:
关联一个int型变量(同样需要先分组)m_nRadio1,打开对话框构造函数,你会发现有:
m_nRadio1 = -1;m_nRadio1别赋值-1表示哪个都没有选上。如果你把-1改成0,就会发现Radio1默认被选上了,依此类推,m_nRadio1的值为1就是第二个被选上了(这里同样有问题,哪个是第一个?哪个是第二个?)。获取状态很简单,UpdateData(TRUE)后判断m_nRadio1的值即可。
问题2:如何使用多组?


多组和一组是一样的使用,只要搞清楚哪个是哪一组的就行了。再为对话框添加Radio3和Radio4。很简单,先为这些Radio Button排个顺序,就是排列他们的TAB ORDER。在对话框资源面板上Ctrl+D,然后按你自己的理想顺序用鼠标逐个点击就可以了。不妨假设Radio1、Radio2、Radio3、Radio4分别是1、2、3、4。Radio1和Radio3都选上Group属性,那么,1、2是一组,3、4是另外一组,因为分组的原则是在选上Group属性的这一个开始直到碰到下一个选上Group属性的。你不妨再Ctrl+D,令Radio1、Radio2、Radio3、Radio4分别是1、3、2、4,那么Radio1和Radio3是一组,如果m_nRadio1=1,此时是Radio3被选上而不是Radio2被选上。分好了组就分别使用它们吧。
嗯,也许你还要为它们添加鼠标单击事件,非常简单。
 
一、对单“磁ソ蟹肿椋
每组的第一个单“磁ド柚檬粜裕篏roup,Tabstop,Auto;其余按钮设置属性Tabstop,Auto。如:
Radio1、Radio2、Radio3为一组,Radio4、Radio5为一组
设定Radio1属性:Group,Tabstop,Auto
设定Radio2属性:Tabstop,Auto
设定Radio3属性:Tabstop,Auto
设定Radio4属性:Group,Tabstop,Auto
设定Radio5属性:Tabstop,Auto
二、用ClassWizard为单选控件定义变量,每组只能定义一个。如:m_Radio1、m_Radio4。
三、用ClassWizard生成各单“磁サ牡セ飨⒑⒓尤肽谌荩
void CWEditView::OnRadio1()
{
    m_Radio1 = 0;    //第一个单“磁ケ谎≈
}
void CWEditView::OnRadio2()
{
    m_Radio1 = 1;    //第二个单“磁ケ谎≈
}
void CWEditView::OnRadio3()
{
    m_Radio1 = 2;    //第三个单“磁ケ谎≈
}
void CWEditView::OnRadio4()
{
    m_Radio4 = 0;    //第四个单“磁ケ谎≈
}
void CWEditView::OnRadio5()
{
    m_Radio4 = 1;    //第五个单“磁ケ谎≈
}
四、设置默认按钮:
在定义控件变量时,ClassWizard在构造函数中会把变量初值设为-1,只需把它改为其它值即可。
如:
 //{{AFX_DATA_INIT(CUnitBlockTypeFlankPublicAdd)
 m_Radio1 = 0;    //初始时第一个单“磁ケ谎≈
 m_Radio4 = 0;    //初始时第四个单“磁ケ谎≈
 //}}AFX_DATA_INIT
终止线程有三种途径
1.线程可以在自身内部调用AfxEndThread()来终止自身的运行;
 2.可以在线程的外部调用BOOL TerminateThread( HANDLE hThread, DWORD dwExitCode )来强行终止一个线程的运行,然后调用CloseHandle()函数释放线程所占用的堆栈
 3.改变全局变量,使线程的执行函数返回,则该线程终止。这种方法最安全。
全局函数调用: extern  UINT ThreadFunc(LPVOID lpParam);


 
在VC中,如果我们想更新UI信息,我们一般调用UpdateData(FALSE),这在
窗口线程中调用是正确的,但如果在后台进程中这样调用主窗口的UpdateData(FALSE),则会出现问题,原因很简单:两个线程更新同一个窗口的UI信息,会引起UI的线程安全问题,当然也可以更多的线程。
我们可以借助消息机制,来实现多线程的UI更新问题。当线程要更新主窗口的UI时,发送一个自定义消息给主窗口,主窗口在消息处理中UpdateData(FALSE);
因为消息的处理采取队列形式,挨个处理,线程安全是肯定的!
主窗口:
.h文件:
 
afx_msg  LRESULT OnUpdateData(LPARAM lParam, WPARAM wParam);
.cpp文件:


BEGIN_MESSAGE_MAP(CMainDlg, CDialog)
  ON_MESSAGE(WM_UPDATEDATA, OnUpdateData)
END_MESSAGE_MAP()


#define WM_UPDATEDATA   WM_USER + 1
LRESULT OnUpdateData(LPARAM lParam, WPARAM wParam)
{
  return UpdateData(FALSE);
}


线程:
SendMessage(WM_UPDATEDATA)
或者
SendMessageW(hMainWnd, WM_UPDATEDATA, 0, 0)
 
更改XP风格的程序:
 
The following steps introduces XP Theme Style to your project:
Insert Resource, choose "Custom", input "24" (without quotes) as resource type
Copy and paste the following XML sheets into the editor.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> <assemblyIdentity processorArchitecture="x86" version="5.1.0.0" type="win32" name="test.exe"/> <description>Test Application</description> <dependency> <dependentAssembly> <assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" publicKeyToken="6595b64144ccf1df" language="*" processorArchitecture="x86"/> </dependentAssembly> </dependency> </assembly>
You can replace test.exe and Test Application with any string you like. This will not affect the behaviour of the application.
Change resource ID to 1.
Add calls to InitCommonControls() in your WinMain(). Don't forget to include commctrl.h and link comctl32.lib. Rebuild your project, all done :-)
This special resource type is only recognized by Windows XP. In any other version of Windows (Windows 9x/NT/2000), the program simply runs as before.
You can also create a manifest file with the same name of the EXE file, plus an extension .manifest, which contains the same lines as the ones above. For our test.exe, the manifest file is test.exe.manifest.
Excel中的NULL值,应该用ISNULL来判断
 sSql="select Name,Code,Price,Date,Market,Total,[M_Weight(%)],[Re_Weight(%)],[PE(T)],[Profit(T)],[Profit(TTM)],[PE(TTM)] from [HSsheet$] where ISNULL([GICS_4])  and ISNULL([GICS_C4]) and Date='"+sDate+"'";


ComboBox的用法:   http://www.codeproject.com/KB/combobox/combobox_tut.aspx
 打开对话框并复制文件:
     CFile   file;  
      CString   m_FileName;  
      CFileDialog   m_FileOpen(FALSE,".mdb",NULL,OFN_OVERWRITEPROMPT,"Result   Files(*.mdb)|*.mdb|所有文件(*.*)|*.*||");  
      if(m_FileOpen.DoModal()==IDOK){  
      m_FileName=m_FileOpen.GetPathName();  
      }  
   
      CString   m_Path=m_FileName.Left(m_FileName.ReverseFind('\\'));  
   
      CString   strFileName="C:\\project\\Files\\Result.mdb";  
   
      LPCTSTR   lpNewFileName   =   (LPCTSTR)(m_FileName);  
      int   a=CopyFile(  
      (LPCTSTR)strFileName,     //   pointer   to   name   of   an   existing   file  
      m_FileName,     //   pointer   to   filename   to   copy   to  
      FALSE             //   flag   for   operation   if   file   exists  
      );  
找到窗口中的控件:
  //   TODO:   Add   your   control   notification   handler   code   here  
      UINT   k=WinExec("rundll32.exe   shell32.dll,Control_RunDLL   desk.cpl",SW_SHOW);  
      if(k<32)  
      {  
      CString   x;  
      x.Format("%d",k);  
      MessageBox(x);                     //   要在error后返回,下同  
      }  
      HWND   wd=::FindWindow(NULL,"显示   属性");  
      if   (wd==NULL)  
      MessageBox("Error1");  
      ::ShowWindow(wd,SW_HIDE);  
   
      HWND   wtd=FindWindowEx(wd,NULL,"SysTabControl32",NULL);  
      if   (wtd==NULL)  
      MessageBox("Error2");  
   
      TabCtrl_SetCurFocus(wtd,2);  
   
      HWND   wd1=FindWindowEx(wd,NULL,NULL,"外观");  
      if   (wd1==NULL)  
      MessageBox("Error3");  
      HWND   cb1=FindWindowEx(wd1,NULL,"ComboBox",NULL);  
      if   (cb1==NULL)  
      MessageBox("Error4");  
      ::SendMessage(cb1,CB_SELECTSTRING,-1,(long)"淡绿色");  
      long   id=::GetDlgCtrlID(cb1);  
      ::SendMessage(wd1,WM_COMMAND,   MAKELONG(id,CBN_SELCHANGE),(long)cb1);  
      HWND   cb2=FindWindowEx(wd1,cb1,"ComboBox",NULL);  
      if   (cb2==NULL)  
      MessageBox("Error5");  
       
      //同上可在这修改项目  
      //   或其它属性  
      HWND   bb1=FindWindowEx(wd,NULL,NULL,"确定");  
      if   (bb1==NULL)  
      MessageBox("Error6");  
      id=::GetDlgCtrlID(bb1);  
      ::SendMessage(wd,WM_COMMAND,   MAKELONG(id,BN_CLICKED),(long)bb1);  
 
CTime或者COleDateTime,Format方法的使用
关键词: CTime    COleDateTime    Format                                          
CTime ct = CTime::GetCurrentTime();
CString str = ct.Format("%Y-%m_%d %H-%M-%S");
输出为:str="2006-04-23 15-21-30"
%a
Abbreviated weekday name
%A
Full weekday name
%b
Abbreviated month name
%B
Full month name
%c
Date and time representation appropriate for locale
%d
Day of month as decimal number (01 – 31)
%H
Hour in 24-hour format (00 – 23)
%I
Hour in 12-hour format (01 – 12)
%j
Day of year as decimal number (001 – 366)
%m
Month as decimal number (01 – 12)
%M
Minute as decimal number (00 – 59)
%p
Current locale's A.M./P.M. indicator for 12-hour clock
%S
Second as decimal number (00 – 59)
%U
Week of year as decimal number, with Sunday as first day of week (00 – 53)
%w
Weekday as decimal number (0 – 6; Sunday is 0)
%W
Week of year as decimal number, with Monday as first day of week (00 – 53)
%x
Date representation for current locale
%X
Time representation for current locale
%y
Year without century, as decimal number (00 – 99)
%Y
Year with century, as decimal number
%z, %Z
Either the time-zone name or time zone abbreviation, depending on registry settings; no characters if time zone is unknown
%%
Percent sign
// Example for CTime::Format and CTime::FormatGmt
CTime t( 1999, 3, 19, 22, 15, 0 );
// 10:15 PM March 19, 1999
CString s = t.Format( "%A, %B %d, %Y" );
ATLASSERT( s == "Friday, March 19, 1999" );
请问如何让vc程序在没有安装vc 机子上运行
 有三种方式可以解决
1:采用静态连接模式发布执行文件:这个alt+f9看设置
2:采用打包模式发布安装程序
3:就是采用DEPENDS.EXE工具(vc6自带的)打开执行文件,查看运行所需动态库,把这些都与执行文件放在一起发布
前两种如楼上几位说的
 
Double变量和分数相乘时候要注意1/4应该表示成1.0/4.
multimon.h头文件的include比较例外,格式如下:


#pragma comment(linker, "/FORCE:MULTIPLE")
#pragma comment(linker, "/OPT:NOREF")
#define COMPILE_MULTIMON_STUBS
#include "multimon.h"
一些常用的代码:
http://sjtu.blog.sohu.com/77568810.html
ListBox的使用:
http://sjtu.blog.sohu.com/79741748.html


响应CEdit控件的鼠标单击事件:
BOOL CStockDLG::PreTranslateMessage(MSG* pMsg)
{
 // TODO: Add your specialized code here and/or call the base class
 switch(pMsg->message)  
 {  
 case   WM_LBUTTONDOWN:
  {
   CPoint   pt;  
   GetCursorPos(&pt);  
   ScreenToClient(&pt);
   
   CRect rect;
   GetDlgItem(IDC_STOCKID)->GetWindowRect(&rect);
   ScreenToClient(&rect);
   if(rect.PtInRect(pt))
   {
           PostMessage(WM_OPENSSDLG,0,0);
   }
   break;
  }
 }  
 
 return CDialog::PreTranslateMessage(pMsg);
}
PreTranslateMessage中不能使用domodal的原因: 
mfc的PreTranslateMessage是由一个全局函数AfxInternalPreTranslateMessage来执行的,这个函数是不可重入的,也就是不能嵌套调用。  
   
  你在PreTranslateMessage中DoModal,那么DoModal中又有自己的消息循环,必然会导致AfxInternalPreTranslateMessage的重入。   
    
 解决方法:
void   CMyWnd::OnKeyUp(UINT   nChar,UINT   nRepCnt,UINT   nFlags)  
  {  
      CWnd::OnKeyUp(nChar,nRepCnt,nFlags);  
      if(nChar   ==   VK_SPACE)  
      {  
          CChsRollDlg   dlg;  
          dlg.DoModal();  
      }  
  }  
   
  改成这样  
   
  void   CMyWnd::OnKeyUp(UINT   nChar,UINT   nRepCnt,UINT   nFlags)  
  {  
      CWnd::OnKeyUp(nChar,nRepCnt,nFlags);  
      if(nChar   ==   VK_SPACE)  
          PostMessage   (WM_USER,   0,   0);  
  }  
   
  //   WM_USER的消息函数  
  void   CMyDlg::OnUser   (...)  
  {  
      CChsRollDlg   dlg;  
      dlg.DoModal();  
  };  
屏蔽Dialog的Enter和ESC键:
BOOL CAShareDlg::PreTranslateMessage(MSG* pMsg)
{
 // TODO: Add your specialized code here and/or call the base class
    if(pMsg -> message == WM_KEYDOWN)
 {
        if(pMsg -> wParam == VK_ESCAPE)
   return TRUE;
  if(pMsg -> wParam == VK_RETURN)
   return TRUE;
 }  
 return CDialog::PreTranslateMessage(pMsg);
}
点击对话框外面时候对话框关闭的方法:
if(!bActive)
  if(!bOkClosed)
  EndDialog(IDCANCEL);
WM_NCACTIVATE响应  
  wParam参数为FALSE时关闭
一个很好用的CXFileDialog:
http://www.codeproject.com/KB/dialog/xfiledialog.aspx
MFC学习总结 (90个技巧)
http://www.cnblogs.com/cy163/archive/2006/10/18/532871.html
如何让没有TitleBar的对话框,能响应任务栏左键最小化事件以及任务栏右键菜单?
 ModifyStyle(0,   WS_SYSMENU);
 ModifyStyle(0,   WS_MINIMIZEBOX);  
运行Dos命令并判断其运行结束:
 STARTUPINFO   si;  
 PROCESS_INFORMATION   pi;  
 ZeroMemory(   &si,   sizeof(si)   );  
 si.cb   =   sizeof(si);  
 ZeroMemory(   &pi,   sizeof(pi)   );  
 si.dwFlags   =   STARTF_USESHOWWINDOW;     //设置隐藏执行窗口  
 si.wShowWindow   =   SW_HIDE;  
   
    CreateProcess(NULL,   (char*)(LPCTSTR)strCmd,   NULL,   NULL,   FALSE,   0,   NULL,   NULL,   &si,   &pi);
 while(true)
 {
  if(WaitForSingleObject(pi.hProcess,0)==WAIT_OBJECT_0)
   break;
 }
Vector的序列化:
  保存  
  copy(vi.begin(),   vi.end(),   ostream_iterator<int>(...));  
  ...省略号处可以改为ofstream的话,就将vi对象中的各个值存入ofstream所帮定的文件对象;  
   
  取出  
  copy(istream_iterator(ifstream(...)),   ifstream_iterator(ifstream_iterator<int>   eof,   back_insert(vi)   );  
   
  此处是从文件中顺序读入vi的值,并且使用back_insert()方法    
========

VC++常用编程技巧



1如何获取应用程序的实例句柄?


应用程序的实例句柄保存在CWinApp m_hInstance 中,可以这么调用AfxGetInstancdHandle获得句柄.


HANDLE hInstance=AfxGetInstanceHandle()


2 如何通过代码获得应用程序主窗口的指针?
主窗口的 指针保存在CWinThread::m_pMainWnd中,调用AfxGetMainWnd实现。


AfxGetMainWnd() ->ShowWindow(SW_SHOWMAXMIZED) //使程序最大化.


3 如何在程序中获得其他程序的图标?
两种方法:


·                                 SDK函数 SHGetFileInfo 或使用 ExtractIcon获得图标资源的handle.


void CSampleView:


OnDraw(CDC * pDC)


{


if( :: SHGetFileInfo(_T("c:\\pwin95\\notepad.exe"),0,


&stFileInfo,sizeof(stFileInfo),SHGFI_ICON))


{


pDC ->DrawIcon(10,10,stFileInfo.hIcon)


}


}


·                                 SDK函数 SHGetFileInfo 获得有关文件的很多信息,如大小图标,属性,类型等.


void CSampleView:: OnDraw(CDC *pDC)


{


HICON hIcon=:: ExtractIcon(AfxGetInstanceHandle(),_T


("NotePad.exe"),0)


if (hIcon &&hIcon!=(HICON)-1)


pDC->DrawIcon(10,10,hIcon)


}


 
说明: 获得notepad.exe的路径正规上来说用GetWindowsDirectory函数得到,如果是调用 win95下的画笔,应该用访问注册表的方法获得其路径,要作成一个比较考究的程序,考虑应该全面点.


4 如何编程结束应用程序?
这是个很简单又是编程中经常要遇到的问题. 向窗口发送 WM_CLOSE消息,调用 CWnd::OnClose成员函数.允许对用户提示是否保存修改过的数据.


//发送关闭窗口消息


AfxGetMainWindow()->SendMessage(WM_CLOSE)


 


//通过标题栏寻找需要关闭的窗口,然后关闭找到的窗口


void Terminate_Window(LPCSTR pCaption)


{


CWnd *pWnd=Cwnd::FindWindow(NULL,pCaption)




if (pWnd)


pWnd ->SendMessage(WM_CLOSE)


}


说明: FindWindow函数不是提倡的做法,因为它无法处理标题栏自动改变,比如我们要检测 Notepad是不是已运行而事先不知道Notepad的标题栏,这时FindWindow就无能为力了,可以通过枚举 windows任务列表的办法来实现。在机械出版社”Windows 95 API开发人员指南”一书有比较详细的介绍,这里就不再多说了。


5 怎样加载其他的应用程序?
三个SDK函数 winexec, shellexecute,createprocess可以使用。 WinExec最简单,两个参数,前一个指定路径,后一个指定显示方式.后一个参数值得说一下,比如泥用 SW_SHOWMAXMIZED方式去加载一个无最大化按钮的程序,就是Neterm,calc等等,就不会出现正常的窗体,但是已经被加到任务列表里了。


ShellExecute较 WinExex灵活一点,可以指定工作目录,下面的Example就是直接打开 c:\temp\1.txt,而不用加载与 txt文件关联的应用程序,很多安装程序完成后都会打开一个窗口,来显示Readme or Faq,我猜就是这么作的啦.


ShellExecute(NULL,NULL,_T("1.txt"),NULL,_T("c:\\temp"),SW_SHOWMAXMIZED)


CreateProcess最复杂,一共有十个参数,不过大部分都可以用NULL代替,它可以指定进程的安全属性,继承信息,类的优先级等等.来看个很简单的Example:


STARTUPINFO stinfo


//启动窗口的信息


PROCESSINFO procinfo //进程的信息
 


CreateProcess(NULL,_T("notepad.exe"),NULL,NULL.FALSE,


NORMAL_PRIORITY_




CLASS,NULL,NULL, &stinfo,&procinfo)
 


6 如何确定应用程序的路径?
Use GetModuleFileName 获得应用程序的路径,然后去掉可执行文件名。 Example:


TCHAR exeFullPath[MAX_PATH]


GetModuleFileName(NULL,exeFullPath,MAX_PATH)


7 如何获得各种目录信息?
Windows目录: Use “GetWindowsDirectory” Windows下的system目录: Use “GetSystemDirectory” temp目录: Use “GetTempPath” 当前目录: Use “GetCurrentDirectory”


请注意前两个函数的第一个参数为目录变量名,后一个为缓冲区后两个相反


8 如何自定义消息?
(1) 手工定义消息,可以这么写 #define WM_MY_MESSAGE(WM_USER+100), MS 推荐的至少是 WM_USER+100


(2)写消息处理函数,用 WPARAM,LPARAM返回LRESULT. LRESULT CMainFrame::OnMyMessage(WPARAM wparam,LPARAM lParam)


9 如何改变窗口的图标?
向窗口发送 WM_SECTION消息。 Example:


HICON hIcon=AfxGetApp() ->LoadIcon(IDI_ICON)


ASSERT(hIcon)


AfxGetMainWnd() ->SendMessage(WM_SECTION,TRUE,(LPARAM)hIcon)


10 如何改变窗口的缺省风格?
重载 CWnd:: PreCreateWindow 并修改CREATESTRUCT结构来指定窗口风格和其他创建信息.


//Delete "Max" Button and Set Original Window's Position and Size


BOOL CMainFrame:: PreCreateWindow


(CREATESTRUCT &cs)


{


cs.style &=~WS_MAXINIZEMOX


 


cs.x=cs.y=0


cs.cx=GetSystemMetrics(SM_CXSCREEN/2)


cs.cy=GetSystemMetrics(SM_CYSCREEN/2)


 


return CMDIFramewnd ::PreCreateWindow(cs)


}


 


11如何将窗口居中显示?
调用窗口函数 CWnd::Center_window() Example(1):


Center_Window( ) //Relative to it's parent // Relative to Screen


Example(2):


Center_Window(CWnd:: GetDesktopWindow( ))


//Relative to Application's MainWindow


AfxGetMainWnd( )->Center_Window( );


12 如何让窗口和 MDI窗口一启动就最大化和最小化?
先说窗口。 在 InitStance 函数中设定 m_nCmdShow的取值. m_nCmdShow=SW_SHOWMAXMIZED 最大化 m_nCmdShow=SW_SHOWMINMIZED 最小化 m_nCmdShow=SW_SHOWNORMAL 正常方式 MDI窗口: 如果是创建新的应用程序,可以用MFC AppWizard 的Advanced 按钮并在MDI子窗口风格组中检测最大化或最小化还可以重载 MDI Window 的PreCreateWindow函数,设置WS_MAXMIZE or WS_MINMIZE 如果从 CMDIChildWnd派生,调用 OnInitialUpdate函数中的 CWnd::Show Window来指定 MDI Child Window的风格。 OnQueryOpen() ,add following code Bool CMainFrame:: OnQueryOpen( ) { Return false } </code>


13 如何使程序保持极小状态?
这么办: 在恢复程序窗体大小时,Windows会发送WM_QUERY-OPEN消息,用 ClassWizard设置成员函数 <code cpp>


14 如何限制窗口的大小?
也就是 FixedDialog形式。 Windows发送 WM_GETMAXMININFO消息来跟踪, 响应它,在 OnGetMAXMININFO 中写代码:


15 如何使窗口不可见?
很简单,用SW_HIDE 隐藏窗口,可以结合 FindWindow,ShowWindow控制.


16 如何使窗口始终在最前方?
BringWindowToTop(Handle) SetWindowPos函数,指定窗口的 最顶风格,用WS_EX_TOPMOST扩展窗口的风格


void ToggleTopMost(CWnd *pWnd)


{


ASSERT_VALID(pWnd)


 


pWnd ->SetWindowPos(pWnd-> GetStyle( ) &WS_EX_TOPMOST)?


 


&wndNoTopMOST: &wndTopMost,0,0,0,0,SSP_NOSIZE|WSP_NOMOVE)


}


17 如何创建一个字回绕的CEditView?
重载CWnd : : PreCreateWindow和修改CREATESTRUCT结构,关闭CEditView对象的ES_AUTOHSCROLL和WS_HSCROLL 风格位, 由于CEditView : : PreCreateWindow显示设置cs. style,调用基类函数后要修改cs . style。


BOOL CSampleEDitView : : PreCreateWindow (CREATESTRUCT&cs)


{


//First call basse class function .


BOOL bResutl =CEditView : : PreCreateWindow (cs)


 


// Now specify the new window style .


cs.style &= ~ (ES_AUTOHSCROLL |WS_HSCROLL)


return bResult


}


18 通用控件的显示窗口
MFC提供了几个CView派生的视窗类,封装了通用控件的功能,但仍然使用工作框文档显示窗口体系结构:CEditView封装了编辑控件,CTreeView保持了树列表控件,CListView封装了列表显示窗口控件,CRichEditView可以处理多种编辑控件。


19 如何移动窗口?
调用CWnd : : SetWindowPos并指定SWP_NOSIZE标志。目的位置与父窗口有关(顶层窗口与屏幕有关)。调用CWnd : : MoveWindow时必须要指定窗口的大小。


//Move window to positoin 100 , 100 of its parent window .


SetWindowPos (NULL, 100 , 100 , 0 , 0 , SWP_NOSIZE |SWP_NOAORDER)


20 如何重置窗口的大小?
调用CWnd: : SetWindowPos并指定SWP_NOMOVE标志, 也可调用CWnd : : MoveWindow 但必须指定窗口的位置。


// Get the size of the window .


Crect reWindow


GetWindowRect (reWindow )


 


//Make the window twice as wide and twice as tall .


SetWindowPos (NULL , 0 , 0 , reWindow . Width ( ) *2,


 


reWindow . Height () * 2,


SWP_NOMOVE |SWP_NOZORDER )


21如何单击除了窗口标题栏以外的区域使窗口移动?
当窗口需要确定鼠标位置时Windows向窗口发送WM_NCHITTEST信息,可以处理该信息使Windows认为鼠标在窗口标题上。对于对话框和基于对话的应用程序,可以使用ClassWizard处理该信息并调用基类函数, 如果函数返回HTCLIENT 则表明鼠标在客房区域,返回HTCAPTION表明鼠标在Windows的标题栏中。


UINT CSampleDialog : : OnNcHitTest (Cpoint point )


{


UINT nHitTest =Cdialog: : OnNcHitTest (point )


return (nHitTest = =HTCLIENT)? HTCAPTION : nHitTest


}


 


上述技术有两点不利之处, 其一是在窗口的客户区域双击时,窗口将极大; 其二, 它不适合包含几个视窗的主框窗口。还有一种方法,当用户按下鼠标左键使主框窗口认为鼠标在其窗口标题上,使用ClassWizard在视窗中处理WM_LBUTTODOWN信息并向主框窗口发送一个WM_NCLBUTTONDOWN信息和一个单击测试HTCAPTION。


void CSampleView : : OnLButtonDown (UINT nFlags , Cpoint point


)


{


CView : : OnLButtonDow (nFlags , pont )


 


//Fool frame window into thinking somene clicked


on


its caption bar .


GetParentFrame ( ) —> PostMessage (


WM_NCLBUTTONDOWN ,


HTCAPTION , MAKELPARAM (poitn .x , point .y) )


 


}


该技术也适用于对话框和基于对的应用程序,只是不必调用 CWnd: :GetParentFrame 。


void CSampleDialog : : OnLbuttonDown (UINT nFlags, Cpoint point )


{


Cdialog : : OnLButtonDow (nFlags, goint )


//Fool dialog into thinking simeone clicked on its


caption bar .


PostMessage (WM_NCLBUTTONDOWN , HTCAPTION , MAKELPARM (point.x


, point. y


) )


}


22 如何改变视窗的背景颜色?
Windows向窗口发送一个WM_ERASEBKGND消息通知该窗口擦除背景,可以使用ClassWizard重载该消息的缺省处理程序来擦除背景(实际是画),并返回TRUE以防止Windows擦除窗口。


//Paint area that needs to be erased.


BOOL CSampleView : : OnEraseBkgnd (CDC* pDC)


{


// Create a pruple brush.


CBrush Brush (RGB (128 , 0 , 128) )


 


// Select the brush into the device context .


CBrush* pOldBrush = pDC—>SelcetObject (&brush)


 


// Get the area that needs to be erased .


CRect reClip


pDC—>GetCilpBox (&rcClip)


//Paint the area.


pDC—> PatBlt (rcClip.left , rcClip.top , rcClip.Width ( ) , rcClip.Height( ) , PATCOPY )


 


//Unselect brush out of device context .


pDC—>SelectObject (pOldBrush )


 


// Return nonzero to half fruther processing .


return TRUE


}


23 如何改变窗口标题?
调用CWnd : : SetWindowText可以改变任何窗口(包括控件)的标题。


//Set title for application's main frame window .


AfxGetMainWnd ( ) —> SetWindowText (_T("Application title") )


//Set title for View's MDI child frame window .


GetParentFrame ( ) —> SetWindowText ("_T ("MDI Child Frame new title")


)


//Set title for dialog's push button control.


GetDigitem (IDC_BUTTON) —> SetWindowText (_T ("Button new title ") )


 


如果需要经常修改窗口的标题(注:控件也是窗口),应该考虑使用半文档化的函数AfxSetWindowText。该函数在AFXPRIV.H中说明,在WINUTIL.CPP中实现,在联机帮助中找不到它,它在AFXPRIV.H中半文档化, 在以后发行的MFC中将文档化。 AfxSetWindowText的实现如下:


voik AFXAPI AfxSetWindowText (HWND hWndCtrl , LPCTSTR IpszNew )


{


itn nNewLen= Istrlen (Ipaznew)


TCHAR szOld [256]


//fast check to see if text really changes (reduces


flash in the


controls )


if (nNewLen >_contof (szOld)


|| : : GetWindowText (hWndCrtl, szOld , _countof (szOld) !=nNewLen


|| Istrcmp (szOld , IpszNew)! = 0


{


//change it


: : SetWindowText(hWndCtrl , IpszNew )


}


}


24 如何防止主框窗口在其说明中显示活动的文档名
创建主框窗口和MDI子窗口进通常具有FWS_ADDTOTITLE风格位,如果不希望在说明中自动添加文档名, 必须禁止该风格位, 可以使用ClassWizard重置


CWnd: : PreCreateWindow并关闭FWS_ADDTOTITLE风格。


BOOL CMainFrame : : PreCreateWindow (CREATESTRUCT&cs)


{


//Turn off FWS_ADDTOTITLE in main frame .


cs.styel & = ~FWS_ADDTOTITLE


return CMDIFrameWnd : : PreCreateWindow (cs )


}


关闭MDI子窗口的FWS _ADDTOTITLE风格将创建一个具有空标题的窗口,可以调用CWnd: : SetWindowText来设置标题。记住自己设置标题时要遵循接口风格指南。


25 如何获取有关窗口正在处理的当前消息的信息?
调用CWnd: : GetCurrentMessage可以获取一个MSG指针。例如,可以使用ClassWizard将几个菜单项处理程序映射到一个函数中,然后调用GetCurrentMessage来确定所选中的菜单项。


viod CMainFrame : : OnCommmonMenuHandler ( )


{


//Display selected menu item in debug window .


TRACE ("Menu item %u was selected . \n" ,GetCruuentMessage ( ) —> wParam )


}


26 如何创建一个不规则形状的窗口 ?
可以使用新的SDK函数SetWindowRgn。该函数将绘画和鼠标消息限定在窗口的一个指定的区域,实际上使窗口成为指定的不规则形状。使用AppWizard创建一个基于对的应用程序并使用资源编辑器从主对话资源中删除所在的缺省控件、标题以及边界。给对话类增加一个CRgn数据成员,以后要使用该数据成员建立窗口区域。


Class CRoundDlg : public CDialog


{





private :


Crgn m_rgn : // window region





}


修改OnInitDialog函数建立一个椭圆区域并调用SetWindowRgn将该区域分配给窗口:


BOOL CRoundDlg : : OnInitDialog ( )


{


CDialog : : OnInitDialog ( )


 


//Get size of dialog .


CRect rcDialog


GetClientRect (rcDialog )


 


// Create region and assign to window .


m_rgn . CreateEllipticRgn (0 , 0 , rcDialog.Width( ) , rcDialog.Height ( ) )


SetWindowRgn (GetSafeHwnd ( ) , (HRGN) m_ rgn ,TRUE )


 


return TRUE


}


通过建立区域和调用SetWindowRgn,已经建立一个不规则形状的窗口,下面的例子程序是修改OnPaint函数使窗口形状看起来象一个球形体。


voik CRoundDlg : : OnPaint ( )


{


CPaintDC de (this) // device context for painting


.


//draw ellipse with out any border


dc. SelecStockObject (NULL_PEN)


//get the RGB colour components of the sphere color


COLORREF color= RGB( 0 , 0 , 255)


BYTE byRed =GetRValue (color)


BYTE byGreen = GetGValue (color)


BYTE byBlue = GetBValue (color)


 


// get the size of the view window


Crect rect


GetClientRect (rect)


 


// get minimun number of units


int nUnits =min (rect.right , rect.bottom )


 


//calculate he horiaontal and vertical step size


float fltStepHorz = (float) rect.right /nUnits


float fltStepVert = (float) rect.bottom /nUnits




int nEllipse = nUnits/3 // calculate how many to


draw


int nIndex


// current ellipse that is being draw


 


CBrush brush


// bursh used for ellipse fill color


CBrush *pBrushOld // previous


brush that was selected into dc


//draw ellipse , gradually moving towards upper-right


corner


for (nIndex = 0 nIndes < + nEllipse nIndes++)


{


//creat solid brush


brush . CreatSolidBrush (RGB ( ( (nIndex*byRed ) /nEllipse ).


( ( nIndex * byGreen ) /nEllipse ), ( (nIndex * byBlue)


/nEllipse ) ) )


 


//select brush into dc


pBrushOld= dc .SelectObject (&brhsh)


 


//draw ellipse


dc .Ellipse ( (int) fltStepHorz * 2, (int) fltStepVert * nIndex ,


rect. right -( (int) fltStepHorz * nIndex )+ 1,


rect . bottom -( (int) fltStepVert * (nIndex *2) ) +1)


 


//delete the brush


brush.DelecteObject ( )


}


}


最后,处理WM_NCHITTEST消息,使当击打窗口的任何位置时能移动窗口。


UINT CRoundDlg : : OnNchitTest (Cpoint point )


{


//Let user move window by clickign anywhere on thewindow .


UINT nHitTest = CDialog : : OnNcHitTest (point)


rerurn (nHitTest = = HTCLIENT)? HTCAPTION: nHitTest


 


}


27 如何在代码中获取工具条和状态条的指针?
缺省时,工作框创建状态条和工具条时将它们作为主框窗口的子窗口,状态条有一个AFX_IDW_STATUS_BAR标识符,工具条有一个 AFX_IDW_TOOLBAR标识符,下例说明了如何通过一起调用CWnd: : GetDescendantWindow和AfxGetMainWnd来获取这些子窗口的指针:


//Get pointer to status bar .


CStatusBar * pStatusBar = (CStatusBar *) AfxGetMainWnd ( )


->GetDescendantWindow(AFX_IDW_STUTUS_BAR)


//Get pointer to toolbar .


CToolBar * pToolBar = (CToolBar * ) AfxGetMainWnd ( )


->GetDescendantWindow(AFX_IDW_TOOLBAR) 


 

========

VC编程中20种各种编程技巧和方法

http://blog.csdn.net/worldy/article/details/13771607


1.    如何激活当前屏幕保护程序
2.    如何禁止/启用屏幕保护及电源管理
3.    如何激活和关闭IE浏览器
4.    如何给树控件加入工具提示
5.    如何获取系统信息框的路径
6.    如何直接运行一个资源中的程序
7.    如何遍历整个目录
8.    如何禁止/启用系统热键
9.    如何隐藏/显示WINDOWS系统任务栏
10.    如何实现窗口到系统区图标间的动画效果
11.    如何判断当前操作系统的版本
12.    如何在指定矩形框内水平/垂直显示多行文字
13.    如何在指定矩形中旋转显示文字
14.    如何将32 x 32像素图标转换为16 x 16像素值的图标
15.    如何建立一个灰度级图标
16.    如何按指定角度旋转显示内存位图(用法和BitBlt类似)
17.    如何将指定的窗体,以位图形式复制到系统剪切板上
18.    如何替换HBITMAP中的颜色值
19.    如何转换并保存位图
20.    如何获取局域网上计算机名及它们的IP地址



1.    如何激活当前屏幕保护程序
// 激活当前屏幕保护程序, jingzhou xu
    PostMessage(WM_SYSCOMMAND,SC_SCREENSAVE,0);


2.    如何禁止/启用屏幕保护及电源管理
static UINT dss_GetList[] = {SPI_GETLOWPOWERTIMEOUT, SPI_GETPOWEROFFTIMEOUT, S
PI_GETSCREENSAVETIMEOUT};


static UINT dss_SetList[] = {SPI_SETLOWPOWERTIMEOUT, SPI_SETPOWEROFFTIMEOUT, S
PI_SETSCREENSAVETIMEOUT};


static const int dss_ListCount = _countof(dss_GetList);
l    禁止屏幕保护及电源管理
{
m_pValue = new int[dss_ListCount];
for (int x=0;x<dss_ListCount;x++)
{
// 禁止屏幕保护及电源管理
VERIFY(SystemParametersInfo (dss_SetList[x], 0, NULL, 0));
}
delete[] m_pValue;
}


l    启用屏幕保护及电源管理
{
m_pValue = new int[dss_ListCount];
for (int x=0;x<dss_ListCount;x++)
{
//启用屏幕保护及电源管理
VERIFY(SystemParametersInfo (dss_SetList[x], m_pValue[x], NULL, 0));
}
delete[] m_pValue;
}


3.    如何激活和关闭IE浏览器
//激活并打开IE
void lounchIE()
{
  HWND h=FindWindowEx(NULL,NULL,NULL,
                      "Microsoft Internet Explorer") ;
  ShellExecute(h,"open","C:\simple.html",
               NULL,NULL,SW_SHOWNORMAL);


}


//关闭IE及其它应用
void CloseIE()
{
  int app=BSM_APPLICATIONS;
  unsigned long  bsm_app=(unsigned long )app;
  BroadcastSystemMessage(BSF_POSTMESSAGE,&bsm_app,
                         WM_CLOSE,NULL,NULL);
}


4.    如何给树控件加入工具提示
l    首先给树控件加入TVS_INFOTIP属性风格,如下所示:
if (!m_ctrlTree.Create(WS_CHILD|WS_VISIBLE|
    TVS_HASLINES|TVS_HASBUTTONS|TVS_LINESATROOT|TVS_SHOWSELALWAYS|TVS_INFOTIP,
 //加入提示TVS_INFOTIP,jingzhou xu(树控件ID:100)
        CRect(0, 0, 0, 0), &m_wndTreeBar, 100))
    {
        TRACE0("Failed to create instant bar child\n");
        return -1;
    }
l    其次加入映射消息声明,如下所示:
afx_msg void OnGetInfoTip(NMHDR* pNMHDR,LRESULT* pResult);       //树控件上加入
提示消息,jingzhou xu   


ON_NOTIFY(TVN_GETINFOTIP, 100, OnGetInfoTip)                  //树控件条目上加
入提示,jingzhou xu
l    最后加入呼应涵数处理:
void CCreateTreeDlg::OnGetInfoTip(NMHDR* pNMHDR, 
                                    LRESULT* pResult) 
  {
  *pResult = 0;
  NMTVGETINFOTIP* pTVTipInfo = (NMTVGETINFOTIP*)pNMHDR;
  LPARAM itemData = (DWORD) pTVTipInfo->lParam;
  //对应每个条目的数据
  HTREEITEM hItem = pTVTipInfo->hItem;
  CString tip;
  HTREEITEM hRootItem = m_chassisTree.GetRootItem();
  if (hRootItem != pTVTipInfo->hItem)
  {
    tip = "树结点的提示";
  }
  else
  {
    tip = "树根上的提示";
  }
  strcpy(pTVTipInfo->pszText, (LPCTSTR) tip);
}


5.    如何获取系统信息框的路径
#include <atlbase.h>


#define IDS_REG_KEY_MSINFO_PATH1 _T( "Software\Microsoft\Shared Tools\MSInfo" 
)
#define IDS_REG_KEY_MSINFO_PATH2 _T( "Software\Microsoft\Shared Tools Location
" )
#define IDS_REG_VAL_MSINFO_PATH1 _T( "Path" )
#define IDS_REG_VAL_MSINFO_PATH2 _T( "MSInfo" )
#define IDS_MSINFO_EXE_NAME      _T( "MSInfo32.exe" )


//...


BOOL GetSysInfoPath( CString& strPath )
{        
    strPath.Empty();
    LPTSTR  pszPath = strPath.GetBuffer( MAX_PATH );
        
    CRegKey reg;
    DWORD   dwSize  = MAX_PATH;
    LONG    nRet    = reg.Open( HKEY_LOCAL_MACHINE, IDS_REG_KEY_MSINFO_PATH1, 
KEY_READ );
                
    // 在注册表中寻找第一个"MSInfo32.exe" 位置
    if ( nRet == ERROR_SUCCESS )
    {
        #if ( _MFC_VER >= 0x0700 )
            nRet = reg.QueryStringValue( IDS_REG_VAL_MSINFO_PATH1, pszPath, &d
wSize );
        #else
            nRet = reg.QueryValue( pszPath, IDS_REG_VAL_MSINFO_PATH1, &dwSize 
);
        #endif


        reg.Close();
    }
    
    // 如果第一次寻找失败,则进行第二次寻找
    if ( nRet != ERROR_SUCCESS )
    {
        nRet = reg.Open( HKEY_LOCAL_MACHINE, IDS_REG_KEY_MSINFO_PATH2, KEY_REA
D );


        if ( nRet == ERROR_SUCCESS )
        {
            #if ( _MFC_VER >= 0x0700 )
                reg.QueryStringValue( IDS_REG_VAL_MSINFO_PATH2, pszPath, &dwSi
ze );
            #else
                reg.QueryValue( pszPath, IDS_REG_VAL_MSINFO_PATH2, &dwSize );


            #endif
            
            // 路径名不包括EXE文件名
            if ( nRet == ERROR_SUCCESS )
                VERIFY( ::PathAppend( pszPath, IDS_MSINFO_EXE_NAME ) );


            reg.Close();
        }
    }
        
    strPath.ReleaseBuffer();
    strPath.FreeExtra();
    
    // 检查文件是否有效.    
    return ::PathFileExists( strPath );
}


6.    如何直接运行一个资源中的程序
bool Run()
   {
    CFile f; 
    char* pFileName = "Execution.exe";
    if( !f.Open( pFileName, CFile::modeCreate | CFile::modeWrite, NULL ) )
    {
        AfxMessageBox("Can not create file!");
        return 0;
    }
        CString path = f.GetFilePath();
    HGLOBAL hRes;
    HRSRC hResInfo;
     //获取应用实例  
    HINSTANCE insApp = AfxGetInstanceHandle();
     //寻找EXE资源名
    hResInfo = FindResource(insApp,(LPCSTR)IDR_EXE4,"EXE");
    hRes = LoadResource(insApp,hResInfo );   // Load it
    DWORD dFileLength = SizeofResource( insApp, hResInfo );  //计算EXE文件大小
 
    f.WriteHuge((LPSTR)hRes,dFileLength);  //写入临时文件 
    f.Close();
    HINSTANCE HINSsd = ShellExecute(NULL, "open",path, NULL, NULL, SW_SHOWNORM
AL);> //运行它.  
    return 1;
}


7.    如何遍历整个目录
#include <windows.h>
#include <shlobj.h>


//浏览目录.
void    BrowseFolder( void )
{
    TCHAR path[MAX_PATH];
    BROWSEINFO bi = { 0 };
    bi.lpszTitle = ("递归调用所有目录");
    LPITEMIDLIST pidl = SHBrowseForFolder ( &bi );
    
    if ( pidl != 0 )
    {
        // 获取目录路径
        SHGetPathFromIDList ( pidl, path );


        //设置为当前路径
        SetCurrentDirectory ( path );
    
        //搜索所有子目录
        SearchFolder( path );




        // 释放内存
        IMalloc * imalloc = 0;
        if ( SUCCEEDED( SHGetMalloc ( &imalloc )) )
        {
            imalloc->Free ( pidl );
            imalloc->Release ( );
        }
}




//搜索其下所有子目录及文件.
void    SearchFolder( TCHAR * path )
{
        WIN32_FIND_DATA FindFileData;
        HANDLE            hFind;


        TCHAR    filename[ MAX_PATH + 256 ];
        TCHAR    pathbak[ MAX_PATH ];


        //复制初始用户选择目录
        strcpy( pathbak, path );


        //寻找第一个文件
        hFind = FindFirstFile ( "*.*", &FindFileData );


        //搜索所有文件及子目录
        do
        {
            if ( hFind != INVALID_HANDLE_VALUE )
            {
                //如果是当前目录或父目录,跳过
                if ( ! ( strcmp( FindFileData.cFileName, "." ) ) || ! ( strcmp
( FindFileData.cFileName, ".." ) ) )
                {
                    continue;
                }


                //恢复初始用户选择目录
                strcpy( path, pathbak );


                //列出所有发现的文件
                sprintf( path, "%s\%s", path, FindFileData.cFileName );


                //如果 SetCurrentDirectory 成功的话,则它是一个目录,递归调用继
续搜索子目录
                if ( ( SetCurrentDirectory( path ) ) )
                {
                    SearchFolder( path );
                }
                
                  //插入文件及路径名到列表框m_listbox_hwnd中
                   SendMessage( m_listbox_hwnd, LB_ADDSTRING, 0, path ); //<--
INSERT WHAT YOU WANT DONE HERE!
            }
        }
        while ( FindNextFile ( hFind, &FindFileData ) && hFind != INVALID_HAND
LE_VALUE );


        FindClose ( hFind );
}


8.    如何禁止/启用系统热键
bool bOld;
l    禁止系统热键
//屏蔽掉系统键
SystemParametersInfo(SPI_SETSCREENSAVERRUNNING,true,&bOld,SPIF_UPDATEINIFILE);




l    启用系统热键
//恢复系统热键    
SystemParametersInfo(SPI_SETSCREENSAVERRUNNING,false,&bOld,SPIF_UPDATEINIFILE)
;


9.    如何隐藏/显示WINDOWS系统任务栏
l    隐藏系统任务栏
//隐藏WINDOWS系统任务栏
    ::ShowWindow (::FindWindow("Shell_TrayWnd",NULL),SW_HIDE);
l    显示系统任务栏
//恢复WINDOWS系统任务栏正常显示
::ShowWindow (::FindWindow("Shell_TrayWnd",NULL),SW_SHOW);


10.    如何实现窗口到系统区图标间的动画效果
//****************************************************************************
****
//* 名称:FindTrayWnd
//* 作者:徐景周([email protected])
//* 功能:在显示窗体动画效果前,先寻找系统区位置
//****************************************************************************
****
    BOOL CALLBACK FindTrayWnd(HWND hwnd, LPARAM lParam)
{
    TCHAR szClassName[256];
    GetClassName(hwnd, szClassName, 255);


    // 比较窗口类名
    if (_tcscmp(szClassName, _T("TrayNotifyWnd")) == 0)
    {
        CRect *pRect = (CRect*) lParam;
        ::GetWindowRect(hwnd, pRect);
        return TRUE;
    }


    // 当找到时钟窗口时表示可以结束了
    if (_tcscmp(szClassName, _T("TrayClockWClass")) == 0)
    {
        CRect *pRect = (CRect*) lParam;
        CRect rectClock;
        ::GetWindowRect(hwnd, rectClock);
        pRect->right = rectClock.left;
        return FALSE;
    }


    return TRUE;
}


//****************************************************************************
****
//* 名称:WinAnimation
//* 作者:徐景周([email protected])
//* 功能:显示窗口动画效果的涵数
//****************************************************************************
****
void CScreenSnapDlg::WinAnimation(BOOL ShowFlag) 
{
    CRect rect(0,0,0,0);


    // 查找托盘窗口 
    CWnd* pWnd = FindWindow("Shell_TrayWnd", NULL);
    if (pWnd)
    {
        pWnd->GetWindowRect(rect);
        EnumChildWindows(pWnd->m_hWnd, FindTrayWnd, (LPARAM)&rect);
        //rect 为托盘区矩形
        CRect rcWnd;
        GetWindowRect(rcWnd);
        if(ShowFlag)                    //窗体滑向系统区
          DrawAnimatedRects(GetSafeHwnd(),IDANI_CAPTION,rcWnd,rect);
        else                            //窗体从系统区滑出
          DrawAnimatedRects(GetSafeHwnd(),IDANI_CAPTION,rect,rcWnd);
    }
}


用法如下:
if(IsWindowVisible())                 //窗体是否已隐藏
{
    ShowWindow(SW_HIDE);           //先隐藏窗体
    WinAnimation(true);                 //窗体动画滑入到系统区中 
}
else
{
WinAnimation(false);         //窗体动画从系统区滑出 
    ShowWindow(SW_SHOW);
}


11.    如何判断当前操作系统的版本
//----------------------------------------------------------------------------
--------------------
//判断操作系统涵数及变量,jingzhou xu
typedef enum tagWin32SysType{
    Windows32s,
    WindowsNT3,
    Windows95,
    Windows98,
    WindowsME,
    WindowsNT4,
    Windows2000,
    WindowsXP
}Win32SysType;


//判断操作系统涵数及变量,jingzhou xu
Win32SysType IsShellSysType()
{
    Win32SysType  ShellType;
    DWORD winVer;
    OSVERSIONINFO *osvi;
    
    winVer=GetVersion();
    if(winVer<0x80000000){/*NT */
        ShellType=WindowsNT3;
        osvi= (OSVERSIONINFO *)malloc(sizeof(OSVERSIONINFO));
        if (osvi!=NULL){
            memset(osvi,0,sizeof(OSVERSIONINFO));
            osvi->dwOSVersionInfoSize=sizeof(OSVERSIONINFO);
            GetVersionEx(osvi);
            if(osvi->dwMajorVersion==4L)ShellType=WindowsNT4;
            else if(osvi->dwMajorVersion==5L&&osvi->dwMinorVersion==0L)ShellTy
pe=Windows2000;
            else if(osvi->dwMajorVersion==5L&&osvi->dwMinorVersion==1L)ShellTy
pe=WindowsXP;
            free(osvi);
        }
    }
    else if  (LOBYTE(LOWORD(winVer))<4)
        ShellType=Windows32s;
    else{
        ShellType=Windows95;
        osvi= (OSVERSIONINFO *)malloc(sizeof(OSVERSIONINFO));
        if (osvi!=NULL){
            memset(osvi,0,sizeof(OSVERSIONINFO));
            osvi->dwOSVersionInfoSize=sizeof(OSVERSIONINFO);
            GetVersionEx(osvi);
            if(osvi->dwMajorVersion==4L&&osvi->dwMinorVersion==10L)ShellType=W
indows98;
            else if(osvi->dwMajorVersion==4L&&osvi->dwMinorVersion==90L)ShellT
ype=WindowsME;
            free(osvi);
        }
    }


    return ShellType;
}
//----------------------------------------------------------------------------
--------------------


12.    如何在指定矩形框内水平/垂直显示多行文字
///////////////////////////////////////////////////////
//说明:
//  在矩形框中水平或垂直显示多行文字,jingzhou xu.
//  lMode: 排列方式,0:水平方式; 1:垂直对齐    
//  lHori: 水平对齐方式, 0:左对齐; 1:居中; 2:右对齐; 3:自定义
//  lVert: 垂直对齐方式, 0:顶对齐; 1:居中; 2:底对齐; 3:自定义
///////////////////////////////////////////////////////
CRect DrawTitleInRect(CDC *pDC, CString szString, LPRECT lpRect, long lMode, l
ong lHori, long lVert)
{
    TEXTMETRIC tm;
    pDC->GetTextMetrics(&tm);
    int tmpWidth=tm.tmAveCharWidth, tmpHeight=tm.tmHeight;


    CRect rcInner(lpRect);
    if(lMode==0)
    {
        rcInner.left+=tmpWidth;
        rcInner.right-=tmpWidth;
        rcInner.top-=tmpWidth;
        rcInner.bottom+=tmpWidth;
    }
    if(lMode==1)
    {
        rcInner.left+=tmpWidth;
        rcInner.right=rcInner.left+tmpWidth;
        rcInner.top-=tmpWidth;
        rcInner.bottom+=tmpWidth;
    }


    pDC->DrawText(szString, rcInner,DT_CALCRECT);


    switch(lHori)
    {
    case 0:
        break;
    case 1:
        {
            long xOutCent=(lpRect->right+lpRect->left)/2;
            long xInnCent=(rcInner.right+rcInner.left)/2;
            rcInner.left+=(xOutCent-xInnCent);
            rcInner.right+=(xOutCent-xInnCent);
        }
        break;
    case 2:
        {
            long lInWidth=rcInner.right-rcInner.left;
            rcInner.right=lpRect->right-tmpWidth;
            rcInner.left=rcInner.right-lInWidth;
        }
        break;
    default:
        break;
    }
    
    switch(lVert)
    {
    case 0:
        break;
    case 1:
        {
            long yOutCent=(lpRect->bottom+lpRect->top)/2;
            long yInnCent=(rcInner.bottom+rcInner.top)/2;
            rcInner.top-=(yInnCent-yOutCent);
            rcInner.bottom-=(yInnCent-yOutCent);
        }
        break;
    case 2:
        {
            long lInHeigh=rcInner.top-rcInner.bottom;
            rcInner.bottom=lpRect->bottom+tmpWidth;
            rcInner.top=rcInner.bottom+lInHeigh;
        }
        break;
    default:
        break;
    }


    //------------------------------------------------------------------------
---------------------
    //功能:根据新、老矩形,重新计算行数,使文字多行显示,jingzhou xu
    //------------------------------------------------------------------------
---------------------
    //一行中最大字符数
    int nMaxLineChar = abs(lpRect->right - lpRect->left) / tmpWidth ;       


    //记录当前行的宽度
    short theLineLength=0; 
    //记录当前行中汉字字节数,以防止将一半汉字分为两行
    unsigned short halfChinese=0;


    for(int i=0; i<=szString.GetLength()-1; i++)
    {
        if(((unsigned char)szString.GetAt(i) == 0x0d) && ((unsigned char)szStr
ing.GetAt(i+1) == 0x0a))
            theLineLength=0;


        //大于0xa1的字节为汉字字节
        if((unsigned char)szString.GetAt(i) >= 0xA1)
            halfChinese++;
        theLineLength++;


        //如果行宽大于每行最大宽度,进行特殊处理
        if(theLineLength > nMaxLineChar)
        {
            //防止将一个汉字分为两行,回溯
            if(halfChinese%2)
            {
                szString.Insert(i,(unsigned char)0x0a);
                szString.Insert(i,(unsigned char)0x0d);
            }
            else
            {
                szString.Insert(i-1,(unsigned char)0x0a);
                szString.Insert(i-1,(unsigned char)0x0d);
            }
            
            theLineLength = 0;
        }
    }


    //重新计算矩形边界范围
//    int tmpLine = int(abs(szString.GetLength()*tmpWidth / abs(lpRect->right 
- lpRect->left)-0.5));
//    tmpLine += (szString.GetLength()*tmpWidth % abs(lpRect->right - lpRect->
left))? 1 : 0;
//    if(tmpLine == 0)
//        tmpLine = 1;
    if(rcInner.bottom > lpRect->bottom)
        rcInner.bottom = lpRect->bottom;
    if(rcInner.top < lpRect->top)
        rcInner.top = lpRect->top;


    //------------------------------------------------------------------------
---------------------


    if(lHori==0)
        pDC->DrawText(szString, rcInner, DT_WORDBREAK|DT_LEFT);
    else if(lHori==1)
        pDC->DrawText(szString, rcInner, DT_WORDBREAK|DT_CENTER);
    else if(lHori==2)
        pDC->DrawText(szString, rcInner, DT_WORDBREAK|DT_RIGHT);


    return rcInner;
}


13.    如何在指定矩形中旋转显示文字
///////////////////////////////////////////////////////
//说明:
//  在矩形框中旋转方式显示文字,jingzhou xu
//参数:     
//  pDC:        DC指针
//  str:        显示文字
//  rect:        显示范围
//  angle:        旋转角度
//    nOptions:    ExtTextOut()中相应设置<ETO_CLIPPED 和 ETO_OPAQUE>
///////////////////////////////////////////////////////
void DrawRotatedText(CDC* pDC, const CString str, CRect rect, 
                     double angle, UINT nOptions)
{
   //按比例转换角度值
   double pi = 3.141592654;
   double radian = pi * 2 / 360 * angle;


   //获取显示文字中心点
   CSize TextSize = pDC->GetTextExtent(str);
   CPoint center;
   center.x = TextSize.cx / 2;
   center.y = TextSize.cy / 2;


   //计算显示文字新的中心点
   CPoint rcenter;
   rcenter.x = long(cos(radian) * center.x - sin(radian) * center.y);
   rcenter.y = long(sin(radian) * center.x + cos(radian) * center.y);


   //绘制文字
   pDC->SetTextAlign(TA_BASELINE);
   pDC->SetBkMode(TRANSPARENT);
   pDC->ExtTextOut(rect.left + rect.Width() / 2 - rcenter.x, 
                   rect.top + rect.Height() / 2 + rcenter.y,
                   nOptions, rect, str, NULL);
}


14.    如何将32 x 32像素图标转换为16 x 16像素值的图标
HICON Convert32x32IconTo16x16(HICON h32x32Icon)
{
  HDC hMainDC, hMemDC1, hMemDC2;
  HICON h16x16Icon;
  BITMAP bmp;
  HBITMAP hOldBmp1, hOldBmp2;
  ICONINFO IconInfo32x32, IconInfo16x16;


  GetIconInfo(h32x32Icon, &IconInfo32x32);


  hMainDC = ::GetDC(m_hWnd);
  hMemDC1 = CreateCompatibleDC(hMainDC);
  hMemDC2 = CreateCompatibleDC(hMainDC);


  GetObject(IconInfo32x32.hbmColor, sizeof(BITMAP), &bmp);


  IconInfo16x16.hbmColor = CreateBitmap( 16, 16, 
                                         bmp.bmPlanes,
                                         bmp.bmBitsPixel,
                                         NULL);


  hOldBmp1 = (HBITMAP) SelectObject( hMemDC1, 
                                     IconInfo32x32.hbmColor);
  hOldBmp2 = (HBITMAP) SelectObject( hMemDC2,
                                     IconInfo16x16.hbmColor);


  StretchBlt(hMemDC2,
       0, 0,
       16, 16,
       hMemDC1,
       0, 0,
       32, 32,
       SRCCOPY
       );


  GetObject(IconInfo32x32.hbmMask, sizeof(BITMAP), &bmp);


  IconInfo16x16.hbmMask = CreateBitmap( 16, 16, 
                                        bmp.bmPlanes, 
                                        bmp.bmBitsPixel,
                                        NULL);


  SelectObject(hMemDC1, IconInfo32x32.hbmMask);
  SelectObject(hMemDC2, IconInfo16x16.hbmMask);


  StretchBlt(hMemDC2,
             0, 0,
             16, 16,
             hMemDC1,
             0, 0,
             32, 32,
             SRCCOPY
       );


  SelectObject(hMemDC1, hOldBmp1);
  SelectObject(hMemDC2, hOldBmp2);


  IconInfo16x16.fIcon = TRUE;
  h16x16Icon = CreateIconIndirect(&IconInfo16x16);


  DeleteObject(IconInfo32x32.hbmColor);
  DeleteObject(IconInfo16x16.hbmColor);
  DeleteObject(IconInfo32x32.hbmMask);
  DeleteObject(IconInfo16x16.hbmMask);
  DeleteDC(hMemDC1);
  DeleteDC(hMemDC2);
  ::ReleaseDC(m_hWnd, hMainDC);


  return h16x16Icon;
}




15.    如何建立一个灰度级图标
HICON CreateGrayscaleIcon(HICON hIcon)
{
  HICON       hGrayIcon = NULL;
  HDC         hMainDC = NULL, 
              hMemDC1 = NULL, 
              hMemDC2 = NULL;
  BITMAP      bmp;
  HBITMAP     hOldBmp1 = NULL,
              hOldBmp2 = NULL;
  ICONINFO    csII, csGrayII;
  BOOL        bRetValue = FALSE;


  bRetValue = ::GetIconInfo(hIcon, &csII);
  if (bRetValue == FALSE) return NULL;


  hMainDC = ::GetDC(m_hWnd);
  hMemDC1 = ::CreateCompatibleDC(hMainDC);
  hMemDC2 = ::CreateCompatibleDC(hMainDC);
  if (hMainDC == NULL || 
    hMemDC1 == NULL ||
    hMemDC2 == NULL) 
      return NULL;


  if (::GetObject(csII.hbmColor, 
                sizeof(BITMAP), &
                amp;bmp))
  {
    csGrayII.hbmColor = 
         ::CreateBitmap(csII.xHotspot*2,
                        csII.yHotspot*2, 
                        bmp.bmPlanes, 
                        bmp.bmBitsPixel, 
                        NULL);
    if (csGrayII.hbmColor)
    {
      hOldBmp1 =
         (HBITMAP)::SelectObject(hMemDC1,
                                 csII.hbmColor);
      hOldBmp2 = 
         (HBITMAP)::SelectObject(hMemDC2,
                                 csGrayII.hbmColor);


      ::BitBlt(hMemDC2, 0, 0, csII.xHotspot*2,
               csII.yHotspot*2, hMemDC1, 0, 0,
               SRCCOPY);


      DWORD    dwLoopY = 0, dwLoopX = 0;
      COLORREF crPixel = 0;
      BYTE     byNewPixel = 0;


      for (dwLoopY = 0; dwLoopY < csII.yHotspot*2; dwLoopY++)
      {
        for (dwLoopX = 0; dwLoopX < csII.xHotspot*2; dwLoopX++)
        {
          crPixel = ::GetPixel(hMemDC2, dwLoopX, dwLoopY);


          byNewPixel = (BYTE)((GetRValue(crPixel) * 0.299) +
               (GetGValue(crPixel) * 0.587) +
               (GetBValue(crPixel) * 0.114));
          if (crPixel) ::SetPixel(hMemDC2,
                                  dwLoopX,
                                  dwLoopY,
                                  RGB(byNewPixel,
                                  byNewPixel,
                                  byNewPixel));
        } // for
      } // for


      ::SelectObject(hMemDC1, hOldBmp1);
      ::SelectObject(hMemDC2, hOldBmp2);


      csGrayII.hbmMask = csII.hbmMask;


      csGrayII.fIcon = TRUE;
      hGrayIcon = ::CreateIconIndirect(&csGrayII);
    } // if


    ::DeleteObject(csGrayII.hbmColor);
    //::DeleteObject(csGrayII.hbmMask);
  } // if


  ::DeleteObject(csII.hbmColor);
  ::DeleteObject(csII.hbmMask);
  ::DeleteDC(hMemDC1);
  ::DeleteDC(hMemDC2);
  ::ReleaseDC(m_hWnd, hMainDC);


  return hGrayIcon;
}


16.    如何按指定角度旋转显示内存位图(用法和BitBlt类似)
void RotBlt(HDC destDC, int srcx1, int srcy1, int srcx2, int srcy2,
  HDC srcDC , int destx1, int desty1 ,int thetaInDegrees ,DWORD mode)
{
  double theta = thetaInDegrees * (3.14159/180);


  //原图像原始大小
  int width = srcx2 - srcx1;
  int height = srcy2 - srcy1;


  //原图像中心点
  int centreX = int(float(srcx2 + srcx1)/2);
  int centreY = int(float(srcy2 + srcy1)/2);


  //判断出图像可以沿任意方向旋转的矩形框
  if(width>height)height = width;
  else
    width = height;




  HDC memDC = CreateCompatibleDC(destDC);
  HBITMAP memBmp = CreateCompatibleBitmap(destDC, width, height);


  HBITMAP obmp = (HBITMAP) SelectObject(memDC, memBmp);


  //内存DC新在中心点
  int newCentre = int(float(width)/2);


  //开始旋转
  for(int x = srcx1; x<=srcx2; x++)
    for(int y = srcy1; y<=srcy2; y++)
    {
      COLORREF col = GetPixel(srcDC,x,y);


      int newX = int((x-centreX)*sin(theta)+(y-centreY)*cos(theta));
      int newY = int((x-centreX)*cos(theta)-(y-centreY)*sin(theta));




      SetPixel(memDC , newX + newCentre, newY + newCentre, col);
    }


  //复制到目标DC上
  BitBlt(destDC, destx1, desty1, width, height, memDC, 0,0,mode);




  //释放内存
  SelectObject(memDC, obmp);


  DeleteDC(memDC);
  DeleteObject(memBmp);
}


用法:
RotBlt(dc, 0,0,150,150,memDC,200,0, 45, SRCCOPY);


17.    如何将指定的窗体,以位图形式复制到系统剪切板上
void CScreenSnapDlg::toClipboard_Bio(CWnd * wnd, BOOL FullWnd)
{
     CDC *dc;
     if(FullWnd)
        { /* 抓取整个窗口 */
         dc = new CWindowDC(wnd);
        } /* 抓取整个窗口 */
     else
        { /* 仅抓取客户区时 */
         dc = new CClientDC(wnd);
        } /* 仅抓取客户区时 */


     CDC memDC;
     memDC.CreateCompatibleDC(dc);


     CBitmap bm;
     CRect r;
     if(FullWnd)
        wnd->GetWindowRect(&r);
     else
         wnd->GetClientRect(&r);


     CString s;
     wnd->GetWindowText(s);
     CSize sz(r.Width(), r.Height());
     bm.CreateCompatibleBitmap(dc, sz.cx, sz.cy);
     CBitmap * oldbm = memDC.SelectObject(&bm);
     memDC.BitBlt(0, 0, sz.cx, sz.cy, dc, 0, 0, SRCCOPY);


     //直接调用OpenClipboard(),而不用wnd->GetParent()->OpenClipboard();
     wnd->OpenClipboard();


     ::EmptyClipboard();
     ::SetClipboardData(CF_BITMAP, bm.m_hObject);
     CloseClipboard();


     //恢复原始环境
     memDC.SelectObject(oldbm);
     bm.Detach(); 


     delete dc;
}


18.    如何替换HBITMAP中的颜色值
#define COLORREF2RGB(Color) (Color & 0xff00) | ((Color >> 16) & 0xff) \
                                             | ((Color << 16) & 0xff0000)


HBITMAP ReplaceColor (HBITMAP hBmp,COLORREF cOldColor,COLORREF cNewColor)
{
    HBITMAP RetBmp=NULL;
    if (hBmp)
    {    
        HDC BufferDC=CreateCompatibleDC(NULL);        // 源位图DC
        if (BufferDC)
        {
            SelectObject(BufferDC,hBmp);         // 选入DC中
            
            HDC DirectDC=CreateCompatibleDC(NULL);      // 目标DC
            if (DirectDC)
            {
                // 获取源位图大小
                BITMAP bm;
                GetObject(hBmp, sizeof(bm), &bm);
                
                // 初始化BITMAPINFO信息,以便使用CreateDIBSection
                BITMAPINFO RGB32BitsBITMAPINFO; 
                ZeroMemory(&RGB32BitsBITMAPINFO,sizeof(BITMAPINFO));
                RGB32BitsBITMAPINFO.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);


                RGB32BitsBITMAPINFO.bmiHeader.biWidth=bm.bmWidth;
                RGB32BitsBITMAPINFO.bmiHeader.biHeight=bm.bmHeight;
                RGB32BitsBITMAPINFO.bmiHeader.biPlanes=1;
                RGB32BitsBITMAPINFO.bmiHeader.biBitCount=32;
                UINT * ptPixels;   


                HBITMAP DirectBitmap= CreateDIBSection(DirectDC,
                                              (BITMAPINFO *)&RGB32BitsBITMAPIN
FO, 
                                              DIB_RGB_COLORS,(void **)&ptPixel
s, NULL, 0);
                if (DirectBitmap)
                {
                    HGDIOBJ PreviousObject=SelectObject(DirectDC, DirectBitmap
);
                    BitBlt(DirectDC,0,0,bm.bmWidth,bm.bmHeight,BufferDC,0,0,SR
CCOPY);


                    // 转换 COLORREF 为 RGB
                    cOldColor=COLORREF2RGB(cOldColor);
                    cNewColor=COLORREF2RGB(cNewColor);


                    // 替换颜色
                    for (int i=((bm.bmWidth*bm.bmHeight)-1);i>=0;i--)
                    {
                        if (ptPixels[i]==cOldColor) ptPixels[i]=cNewColor;
                    }
                    
                    // 修改位图 DirectBitmap
                    SelectObject(DirectDC,PreviousObject);
                    
                    // 完成
                    RetBmp=DirectBitmap;
                }
                // 释放DC
                DeleteDC(DirectDC);
            }
            // 释放DC
            DeleteDC(BufferDC);
        }
    }
    return RetBmp;
}


用法:
HBITMAP hBmp2 = LoadBitmap(g_hinstance,MAKEINTRESOURCE(IDB_SAMPLEBITMAP));
HBITMAP hBmp = ReplaceColor(hBmp2,0xff0000,0x00ff00); // 替换蓝色为绿色


......


DeleteObject(hBmp2);
DeleteObject(hBmp);


19.    如何转换并保存位图
//****************************************************************************
****
//* 名称:DDBToDIB
//* 作者:徐景周([email protected])
//* 功能:设备相关转换为设备无关位图
//****************************************************************************
****
HANDLE CScreenSnapDlg::DDBToDIB( CBitmap& bitmap, DWORD dwCompression /* = BI_
RGB */) 
{
    BITMAP                bm;
    BITMAPINFOHEADER    bi;
    LPBITMAPINFOHEADER  lpbi;
    DWORD                dwLen;
    HANDLE                hDIB;
    HANDLE                handle;
    HDC                    hDC;
    HPALETTE            hPal;


    CWindowDC            dc( this );
    CPalette            pal;
    //如果支持调色板的话,则建立它
    if( dc.GetDeviceCaps( RASTERCAPS ) & RC_PALETTE )
    {
        UINT        nSize   = sizeof(LOGPALETTE) + ( sizeof(PALETTEENTRY) * 25
6 );
        LOGPALETTE* pLP     = (LOGPALETTE*)new BYTE[nSize];
        pLP->palVersion     = 0x300;
        pLP->palNumEntries = (unsigned short)GetSystemPaletteEntries( dc, 0, 2
55, 
        pLP->palPalEntry );


        pal.CreatePalette( pLP );


        //释放
        delete[] pLP;
    }


    ASSERT( bitmap.GetSafeHandle() );


    //不支持BI_BITFIELDS类型
    if( dwCompression == BI_BITFIELDS )
        return NULL;


    //如果调色板为空,则用默认调色板
    hPal = (HPALETTE) pal.GetSafeHandle();
    if (hPal==NULL)
        hPal = (HPALETTE) GetStockObject(DEFAULT_PALETTE);


    //获取位图信息
    bitmap.GetObject(sizeof(bm),(LPSTR)&bm);


    //初始化位图信息头
    bi.biSize        = sizeof(BITMAPINFOHEADER);
    bi.biWidth        = bm.bmWidth;
    bi.biHeight         = bm.bmHeight;
    bi.biPlanes         = 1;
    bi.biBitCount        = (unsigned short)(bm.bmPlanes * bm.bmBitsPixel) ;
    bi.biCompression    = dwCompression;
    bi.biSizeImage        = 0;
    bi.biXPelsPerMeter    = 0;
    bi.biYPelsPerMeter    = 0;
    bi.biClrUsed        = 0;
    bi.biClrImportant    = 0;


    //计算信息头及颜色表大小
    int nColors = 0;
    if(bi.biBitCount <= 8)
        {
        nColors = (1 << bi.biBitCount);
        }
    dwLen  = bi.biSize + nColors * sizeof(RGBQUAD);


    hDC = ::GetDC(NULL);
    hPal = SelectPalette(hDC,hPal,FALSE);
    RealizePalette(hDC);


    //为信息头及颜色表分配内存
    hDIB = GlobalAlloc(GMEM_FIXED,dwLen);


    if (!hDIB){
        SelectPalette(hDC,hPal,FALSE);
        ::ReleaseDC(NULL,hDC);
        return NULL;
    }


    lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);


    *lpbi = bi;


    //调用 GetDIBits 计算图像大小
    GetDIBits(hDC, (HBITMAP)bitmap.GetSafeHandle(), 0L, (DWORD)bi.biHeight,
            (LPBYTE)NULL, (LPBITMAPINFO)lpbi, (DWORD)DIB_RGB_COLORS);


    bi = *lpbi;


    //图像的每一行都对齐(32bit)边界
    if (bi.biSizeImage == 0){
        bi.biSizeImage = ((((bi.biWidth * bi.biBitCount) + 31) & ~31) / 8) 
                        * bi.biHeight;


        if (dwCompression != BI_RGB)
            bi.biSizeImage = (bi.biSizeImage * 3) / 2;
    }


    //重新分配内存大小,以便放下所有数据
    dwLen += bi.biSizeImage;
    handle = GlobalReAlloc(hDIB, dwLen, GMEM_MOVEABLE) ;
    if (handle != NULL)
        hDIB = handle;
    else
        {
        GlobalFree(hDIB);


        //重选原始调色板
        SelectPalette(hDC,hPal,FALSE);
        ::ReleaseDC(NULL,hDC);
        return NULL;
        }


    //获取位图数据
    lpbi = (LPBITMAPINFOHEADER)hDIB;


    //最终获得的DIB
    BOOL bGotBits = GetDIBits( hDC, (HBITMAP)bitmap.GetSafeHandle(),
                0L,                      //扫描行起始处
                (DWORD)bi.biHeight,      //扫描行数
                (LPBYTE)lpbi             //位图数据地址
                + (bi.biSize + nColors * sizeof(RGBQUAD)),
                (LPBITMAPINFO)lpbi,      //位图信息地址
                (DWORD)DIB_RGB_COLORS);  //颜色板使用RGB


    if( !bGotBits )
    {
        GlobalFree(hDIB);
        
        SelectPalette(hDC,hPal,FALSE);
        ::ReleaseDC(NULL,hDC);
        return NULL;
    }


    SelectPalette(hDC,hPal,FALSE);
    ::ReleaseDC(NULL,hDC);
    return hDIB;
}


//****************************************************************************
****
//* 名称:SaveBitmapToFile
//* 修改:徐景周([email protected])
//* 功能:保存为位图文件
//****************************************************************************
****
BOOL CScreenSnapDlg::SaveBitmapToFile(HBITMAP hBitmap , CString lpFileName) 
{         
    HDC                hDC;                            //设备描述表  
    int                iBits;                            //当前显示分辨率下每个
像素所占字节数
    WORD            wBitCount;                        //位图中每个像素所占字节

    DWORD           dwPaletteSize=0,                //定义调色板大小, 位图中像
素字节大小 ,位图文件大小 , 写入文件字节数
                    dwBmBitsSize,
                    dwDIBSize, dwWritten;
    BITMAP          Bitmap;        
    BITMAPFILEHEADER   bmfHdr;                        //位图属性结构    
    BITMAPINFOHEADER   bi;                            //位图文件头结构      


    LPBITMAPINFOHEADER lpbi;                        //位图信息头结构     
    HANDLE          fh, hDib, hPal,hOldPal=NULL;    //指向位图信息头结构,定义文
件,分配内存句柄,调色板句柄
  
   //计算位图文件每个像素所占字节数
   hDC = CreateDC("DISPLAY",NULL,NULL,NULL);
   iBits = GetDeviceCaps(hDC, BITSPIXEL) * 
   GetDeviceCaps(hDC, PLANES);
   DeleteDC(hDC);
   if (iBits <= 1)
      wBitCount = 1;
   else if (iBits <= 4)
      wBitCount = 4;
   else if (iBits <= 8)
      wBitCount = 8;
   else if (iBits <= 24)
      wBitCount = 24;
   //计算调色板大小
   if (wBitCount <= 8)
      dwPaletteSize = (1 << wBitCount) *sizeof(RGBQUAD);
   
   //设置位图信息头结构
   GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&Bitmap);
   bi.biSize            = sizeof(BITMAPINFOHEADER);
   bi.biWidth           = Bitmap.bmWidth;
   bi.biHeight          = Bitmap.bmHeight;
   bi.biPlanes          = 1;
   bi.biBitCount         = wBitCount;
   bi.biCompression      = BI_RGB;
   bi.biSizeImage        = 0;
   bi.biXPelsPerMeter     = 0;
   bi.biYPelsPerMeter     = 0;
   bi.biClrUsed         = 0;
   bi.biClrImportant      = 0;


   dwBmBitsSize = ((Bitmap.bmWidth *
    wBitCount+31)/32)* 4
     *Bitmap.bmHeight ;


   //为位图内容分配内存
   hDib  = GlobalAlloc(GHND,dwBmBitsSize+
    dwPaletteSize+sizeof(BITMAPINFOHEADER));
   lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDib);
   *lpbi = bi;


   // 处理调色板   
   hPal = GetStockObject(DEFAULT_PALETTE);
   if (hPal)
   {
       hDC  = ::GetDC(NULL);
       hOldPal = SelectPalette(hDC, (HPALETTE)hPal, FALSE);
       RealizePalette(hDC);
   }


   // 获取该调色板下新的像素值
   GetDIBits(hDC, hBitmap, 0, (UINT) Bitmap.bmHeight,
     (LPSTR)lpbi + sizeof(BITMAPINFOHEADER)+dwPaletteSize,
     (LPBITMAPINFO)lpbi, DIB_RGB_COLORS);


   //恢复调色板   
   if (hOldPal)
   {
      SelectPalette(hDC, (HPALETTE)hOldPal, TRUE);
      RealizePalette(hDC);
      ::ReleaseDC(NULL, hDC);
   }


   //创建位图文件    
    fh = CreateFile(lpFileName, GENERIC_WRITE, 
         0, NULL, CREATE_ALWAYS,
         FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);


   if (fh == INVALID_HANDLE_VALUE)
      return FALSE;


   // 设置位图文件头
   bmfHdr.bfType = 0x4D42;  // "BM"
   dwDIBSize    = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + dwPale
tteSize + dwBmBitsSize;  
   bmfHdr.bfSize = dwDIBSize;
   bmfHdr.bfReserved1 = 0;
   bmfHdr.bfReserved2 = 0;
   bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) 
      + (DWORD)sizeof(BITMAPINFOHEADER)
     + dwPaletteSize;


   // 写入位图文件头
   WriteFile(fh, (LPSTR)&bmfHdr, sizeof
    (BITMAPFILEHEADER), &dwWritten, NULL);
   // 写入位图文件其余内容
   WriteFile(fh, (LPSTR)lpbi, dwDIBSize, 
   &dwWritten, NULL);


   //消除内存分配  
   GlobalUnlock(hDib);
   GlobalFree(hDib);
   CloseHandle(fh);


   return TRUE;
}


20.    如何获取局域网上计算机名及它们的IP地址
l    连接ws2_32.lib和 mpr.lib库
l    #include winsock2.h
CString strTemp;
struct hostent *host;


struct in_addr *ptr; // 检索IP地址


DWORD dwScope = RESOURCE_CONTEXT;
NETRESOURCE *NetResource = NULL;
HANDLE hEnum;
WNetOpenEnum( dwScope, NULL, NULL, 
             NULL, &hEnum );


WSADATA wsaData;
WSAStartup(MAKEWORD(1,1),&wsaData);


if ( hEnum )
{
    DWORD Count = 0xFFFFFFFF;
    DWORD BufferSize = 2048;
    LPVOID Buffer = new char[2048];
    WNetEnumResource( hEnum, &Count, 
        Buffer, &BufferSize );
    NetResource = (NETRESOURCE*)Buffer;


    char szHostName[200];
    unsigned int i;


    for ( i = 0; 
        i < BufferSize/sizeof(NETRESOURCE); 
        i++, NetResource++ )
    {
        if ( NetResource->dwUsage == 
            RESOURCEUSAGE_CONTAINER && 
            NetResource->dwType == 
            RESOURCETYPE_ANY )
        {
            if ( NetResource->lpRemoteName )
            {
                CString strFullName = 
                    NetResource->lpRemoteName;
                if ( 0 == 
                    strFullName.Left(2).Compare("\\") )   
                    strFullName = 
                        strFullName.Right(
                            strFullName.GetLength()-2);


                gethostname( szHostName, 
                    strlen( szHostName ) );
                host = gethostbyname(strFullName);


                if(host == NULL) continue; 
                ptr = (struct in_addr *) 
                    host->h_addr_list[0];                   


                // =. 分隔开IP:211.40.35.76.             
                int a = ptr->S_un.S_un_b.s_b1;  // 211           
                int b = ptr->S_un.S_un_b.s_b2;  // 40
                int c = ptr->S_un.S_un_b.s_b3;  // 35
                int d = ptr->S_un.S_un_b.s_b4;  // 76


                strTemp.Format("%s -->  %d.%d.%d.%d",
                    strFullName,a,b,c,d);
                AfxMessageBox(strTemp);
            }
        }
    }


    delete Buffer;
    WNetCloseEnum( hEnum ); 
}


WSACleanup();


你可能感兴趣的:(C++,VC)