面对现实,超越自己
逆水行舟,不进则退
posts - 269,comments - 32,trackbacks - 0
本文转自:http://blog.csdn.net/welcome_ck/article/details/236259

何谓消息、消息处理函数、消息映射?
消息简单的说就是指通过输入设备向程序发出指令要执行某个操作。具体的某个操作是你的一系列代码。称为消息处理函数。在SDK中消息其实非常容易理解,当窗口建立后便会有一个函数(窗口处理函数)开始执行一个消息循环,我们还可以清楚的看到消息处理的脉络。一个switch case语句就可以搞定,消息循环直到遇到WM_QUIT消息才会结束,其余的消息均被拦截后调用相应的处理函数。但在封装了API的MFC中,消息似乎变的有些复杂了,我们看不到熟悉的switch case语句了,取而代之的是一个叫消息映射的东西。为什么MFC要引入消息映射机制,你可以想象一下,在现在的程序开发活动中,你的一个程序是否拥有多个窗体,主窗口就算只有一个,那菜单、工具条、控件这些都是子窗口,那我们需要写多少个switch case,并且还要为每个消息分配一个消息处理函数,这样做是多么的复杂呀。因此MFC采用了一种新的机制。利用一个数组,将窗口消息和相对应的消息处理函数进行映射,你可以理解成这是一个表。这种机制就是消息映射。这张表在窗口基类CWnd定义,派生类的消息映射表如果你没有动作它是空的,也就是说如果你不手工的增加消息处理函数,则当派生窗口接受一个消息时会执行父类的消息处理函数。这样做显然是高效的。
MFC提供的消息结构
同时MFC定义了下面的两个主要结构:
AFX_MSGMAP_ENTRY
struct AFX_MSGMAP_ENTRY{
UINT nMessage;   // Windows消息的ID号
UINT nCode;  // 控制消息的通知
UINT nID;    // Windows控制消息的ID
UINT nLastID;   //表示是一个指定范围的消息被映射的范围
UINT nSig;  //表示消息的动作标识
AFX_PMSG pfn;    // 指向消息处理函数的指针
};
AFX_MSGMAP
struct AFX_MSGMAP{
#ifdef _AFXDLL
const AFX_MSGMAP* (PASCAL* pfnGetBaseMap)();
#else
const AFX_MSGMAP* pBaseMap;
#endif
const AFX_MSGMAP_ENTRY* lpEntries;
};
///AFX_MSGMAP可以得到基类的消息映射入口地址和得到本身的消息映射入口地址。

MFC下一个消息的处理过程是一般是这样的。
1、_AfxCbtFilterHook截获消息(这是一个钩子函数)
2、_AfxCbtFilterHook把窗口过程设定为AfxWndProc。
3、函数AfxWndProc接收Windows操作系统发送的消息。
4、函数AfxWndProc调用函数AfxCallWndProc进行消息处理。
5、函数AfxCallWndProc调用CWnd类的方法WindowProc进行消息处理。

如何添加自己的消息?
我们已经了解了WINDOW的消息机制,如何加入我们自己的消息呢?好我们来看
一个标准的消息处理程序是这个样子的
在 CWnd 类中预定义了标准 Windows 消息 (WM_XXXX  WM是WINDOW MESSAGE的缩写) 的默认处理程序。类库基于消息名命名这些处理程序。例如,WM_PAINT 消息的处理程序在 CWnd 中被声明为:
afx_msg void OnPaint();
afx_msg 关键字通过使这些处理程序区别于其他 CWnd 成员函数来表明 C++ virtual 关键字的作用。但是请注意,这些函数实际上并不是虚拟的,而是通过消息映射实现的。我们在本文的一开始便说明了为什么要这样做。
所有能够进行消息处理的类都是基于CCmdTarget类的,也就是说CCmdTarget类是所有可以进行消息处理类的父类。CCmdTarget类是MFC处理命令消息的基础和核心。

若要重写基类中定义的处理程序,只需在派生类中定义一个具有相同原型的函数,并创建此处理程序的消息映射项。我们通过ClassWizard可以建立大多数窗口消息或自定义的消息,通过ClassWizard可以自动建立消息映射,和消息处理函数的框架,我们只需要把我们要做的事情填空,添加你要做的事情到处理函数。这个非常简单,就不细说了。但是也许我们需要添加一些ClassWizard不支持的窗口消息或自定义消息,那么就需要我们亲自动手建立消息映射和消息处理的框架,通常步骤如下:
第一步:定义消息。Microsoft推荐用户自定义消息至少是WM_USER+100,因为很多新控件也要使用WM_USER消息。
#define WM_MYMESSAGE (WM_USER + 100)

第二步:实现消息处理函数。该函数使用WPRAM和LPARAM参数并返回LPESULT。
LPESULT CMainFrame::OnMyMessage(WPARAM wParam, LPARAM lParam)
{
// TODO: 处理用户自定义消息,填空就是要填到这里。
return 0;
}
第三步:在类头文件的AFX_MSG块中说明消息处理函数:
// {{AFX_MSG(CMainFrame)
afx_msg LRESULT OnMyMessage(WPARAM wParam, LPARAM lParam);
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
第四步:在用户类的消息块中,使用ON_MESSAGE宏指令将消息映射到消息处理函数中。
ON_MESSAGE( WM_MYMESSAGE, OnMyMessage )

可以看出,用户自定义的消息和我们通过ClassWizard添加的消息一样,都是利用了ON_MESSAGE宏,建立的消息映射。

其实消息类别可以分成多种,上面说的只是其中之一。有三种主要的消息类别:(以下部分摘自MSDN)
1、Windows 消息
此类消息主要包括以前缀 WM_ 开头的消息,WM_COMMAND 除外。Windows 消息由窗口和视图处理。此类消息往往带有用于确定如何处理消息的参数。
2、控件通知
此类消息包括从控件和其他子窗口发送到其父窗口的 WM_COMMAND 通知消息。例如,当用户在编辑控件 (Edit Control) 中执行可能更改文本的操作后,该编辑控件 (Edit Control) 将向其父级发送包含 EN_CHANGE 控件通知代码的 WM_COMMAND 消息。该消息的窗口处理程序以某种适当的方式响应此通知消息,例如在控件中检索该文本。
框架像传送其他 WM_ 消息一样传送控件通知消息。但是有一个例外的情况,即当用户单击按钮时由按钮发送的 BN_CLICKED 控件通知消息。该消息被作为命令消息特别处理,并像其他命令一样传送。
3、命令消息
此类消息包括用户界面对象(菜单、工具栏按钮和快捷键)发出的 WM_COMMAND 通知消息。框架处理命令的方式与处理其他消息不同,可以使用更多种类的对象处理命令。
Windows 消息和控件通知消息由窗口来处理(窗口是从 CWnd 类派生的类的对象)。包括 CFrameWnd、CMDIFrameWnd、CMDIChildWnd、CView、CDialog 以及从这些基类派生的您自己的类。这些对象封装了 HWND——Windows 窗口的句柄。
命令消息可以由范围更广的对象(文档、文档模板以及应用程序对象本身)处理,而不仅仅由窗口和视图处理。当某一命令直接影响到某个特定对象时,应当让该对象处理此命令。例如,“文件”菜单中的“打开”命令在逻辑上与应用程序相关联:该应用程序接收到此命令时会打开指定的文档。因此“打开”命令的处理程序是应用程序类的成员函数。

命令消息我们比较常见的便是菜单项和工具条了,大家可以看到他的消息映射宏和窗口消息不太一样,一般的形式是这样的
ON_COMMAND(id,memberFxn)
第一个参数是命令ID,一个ID号对应一个消息处理,当然你可以让多个ID共用一个处理函数。常见的应用例如:菜单项打开文档的ID和工具条按钮打开文档的ID同时使用一个处理函数,或者直接将它们的ID设成相同的。

还有一种消息叫通知消息。例如树型控件的等一些复杂的控件在单击后需要传递更多的信息,例如光标的位置和当前项的一个结构,所以MFC为控件的每个通知消息也定义了一个宏,它长成了这个样子:
ON_CONTROL(EN_CHANGE,id,memberFxn)

还有很多种消息存在于MFC,宏定义有区别,大家可以触类旁通。

窗口消息有上百个。你可以从MSDN上查到WM_开头的,或者查看CWnd的成员函数,会给你列出很多,别忘了还有很多非窗口消息

其他链接:http://blog.csdn.net/liufei_learning/article/details/5903287
                     http://www.cnblogs.com/lantionzy/archive/2009/10/10/1580428.html
posted @ 2012-04-19 16:06 王海光 阅读(1947) | 评论 (0)编辑 收藏
本文转自:http://hi.baidu.com/agodliness/blog/item/8ad01d0a21734728b0351d70.html

环境变量是指那些可为系统所使用的包含有环境信息的字符串,根据级别的不同而分为系统环境变量和用户环境变量,并以此给出诸如文件搜索路径,存放临时文件的目录等与系统和用户相关的环境变量。下表列出了用于环境变量访问的函数。

                       环境变量访问函数
 ────────────────────────────────────
               环境变量函数                   函数说明
 ────────────────────────────────────
 GreateEnvironmentBlock()      为特定的用户创建一个环境块
 ────────────────────────────────────
 DestoryEnvironmentBlock()     释放由CreateEnvironmentBlock()创建的环境块
 ────────────────────────────────────
 GetEnvironmentStrings()       得到当前进程的环境块的地址
 ────────────────────────────────────
 FreeEnvironmentStrings()      释放由GetEnvironmentStrings()得到的环境块
 ────────────────────────────────────
 GetEnvironmentVariable()      得到指定环境变量的相关信息
 ────────────────────────────────────
 SetEnvironmentVariable()      添加,修改或删除一个指定的环境变量
 ───────────────────────────────────

 注:环境块是指与进程相关的,包含有环境变量名及其对应值的一个在进程地址空间内分配的内存块。

   下面的给出的代码演示了对进程的环境变量进行读,写访问的基本操作过程。

  

 1 // 待操作的环境变量名
 2  CString sEnvironmentName = "PUBLIC";
 3  char cBuffer[256];
 4 
 5  // 读取环境变量信息
 6   DWORD dwRet = GetEnvironmentVariable(sEnvironmentName, cBuffer, 256);
 7     if (dwRet == 0)
 8     {
 9          // 如果环境变量不存在,则创建之
10     CString sEnvironmentValue("<进程的环境变量测试程序>");
11 
12     BOOL bRet=SetEnvironmentVariable(sEnvironmentName,sEnvironmentValue);
13       if (bRet == TRUE) AfxMessageBox("环境变量设置完毕!");
14                  else AfxMessageBox("环境变量设置失败!"); 
15     }else{
16            // 如果环境变量存在,显示环境变量内容
17             CString sMessage("环境变量PUBLIC值为:");
18             sMessage += CString(cBuffer);
19             AfxMessageBox(sMessage);
20     }


    进程的环境变量是具有可继承性的,即在创建子进程时,是可以同时将环境变量传递给子进程的。在创建子进程的过程中,可以有父进程负责控制子进程,子进程可以继承那些环境变量,一旦子进程创建完毕,父进程即失去对子进程环境变量的控制。实际上,子进程从父进程继承来的环境变量只是父进程环境变量的一个副本,子进程对其环境变量的修改并不会影响到父进程。


posted @ 2012-04-17 12:21 王海光 阅读(1660) | 评论 (0)编辑 收藏
VBS中启动exe程序:
1 set ws=WScript.CreateObject("WScript.Shell"
2 ws.Run "AutoUpdateEx.exe",0,true
3 ws.Run "打印配置工具.exe",0,true
4 ws.Run "DOMASClientMonitor.exe",0,true
5 ws.Run "PrinterMonitorEx.exe",0,false

VBS中启动exe程序绝对路径:
1 set ws=WScript.CreateObject("WScript.Shell"
2 ws.Run """C:\Program Files\Test\AutoUpdateEx.exe""",0,true
3 ws.Run """C:\Program Files\Test\DOMASClientMonitor.exe""",0,false
4 ws.Run """C:\Program Files\Test\PrinterMonitorEx.exe""",0,false
5 ws.Run """C:\Program Files\Test\打印配置工具.exe""",0,false

ws.Run实际参数是"C:\Program Files\Test\AutoUpdateEx.exe",因为带空格,先将它括起来作为一个整体,而两侧的"按要求应该用转义""表示,故成为""C:\Program Files\Test\AutoUpdateEx.exe"",而Run本身调用参数就得在外部加一对引号,故共有三对引号。用msgbox"""C:\Program Files\Test\AutoUpdateEx.exe"""可验证结果为"C:\Program Files\Test\AutoUpdateEx.exe"。对于Run方法,可以统一都用三个引号,ws.Run"""C:\"""同样可以解析;本例也可用ws.Run"C:\progra~1\Test\AutoUpdateEx.exe"来实现。

posted @ 2012-04-16 12:41 王海光 阅读(2774) | 评论 (0)编辑 收藏
写注册表字符串值:
 
 1     //访问注册表,hKEY则保存此函数所打开的键的句柄
 2     HKEY hKey;
 3     //如果无法打开hKEY,则创建
 4     if (ERROR_SUCCESS != RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\EMFPrinter"
 5         , 0, KEY_READ|KEY_WRITE|KEY_SET_VALUE, &hKey))
 6     {
 7         if (ERROR_SUCCESS != RegCreateKey(HKEY_LOCAL_MACHINE,"SOFTWARE\\EMFPrinter",&hKey))
 8 
 9         {    
10             LOG("创建注册表 %s 失败", hKey);
11             return FALSE;
12         }
13     }
14 
15     DWORD    dwTypeString = REG_SZ;
16     TCHAR    pDirBuf[255= {0};
17     DWORD    len = 255;
18     //如果无法查询有关的注册表信息,设置相关注册表信息
19     if (ERROR_SUCCESS != RegQueryValueEx(hKey, ""0&dwTypeString,(LPBYTE)pDirBuf, &len))
20     {
21         RegSetValueEx(hKey, ""0, REG_SZ,NULL, 0);    
22     }    
23     RegCloseKey(hKey);

读取注册表中DWORD值并且改变其值:

 1 CString sPrinterRegPath = "SYSTEM\\CurrentControlSet\\Control\\Print\\Printers\\dd";
 2     HKEY hkey;
 3     if (ERROR_SUCCESS != RegOpenKeyEx(HKEY_LOCAL_MACHINE, sPrinterRegPath, 0, KEY_READ|KEY_WRITE|KEY_SET_VALUE, 
 4         &hkey)) 
 5     {
 6         LOG("打开打印机注册表项%s失败", sPrinterRegPath);
 7         return FALSE;
 8     }
 9 
10     DWORD    dwTypeString = REG_SZ;
11     DWORD    len = 255;
12     DWORD    dwValue;
13     DWORD   dwData = 1;
14     //如果存在有关的注册表信息,修改相关注册表信息
15     if (ERROR_SUCCESS == RegQueryValueEx(hkey, "123"0&dwTypeString,(BYTE*)&dwValue, &len))
16     {
17         if (ERROR_SUCCESS == RegSetValueEx(hkey, "123"0, REG_DWORD,(LPBYTE)&dwData, sizeof(DWORD)))
18         {
19             LOG("修改注册表成功!")
20         }   
21     }    


posted @ 2012-04-13 17:54 王海光 阅读(1008) | 评论 (0)编辑 收藏
本文转自:http://www.cppblog.com/tgh621/archive/2008/04/15/47100.aspx?opt=admin

 1 #include <stdlib.h> #include <iostream>
 2 using namespace std;
 3 
 4 class tgh
 5 {
 6 public:
 7     tgh():i(3){}
 8     const int a() const {return 5;}
 9     int a(){return i;}
10 protected:
11     int i;
12 private:
13 };
14 
15 void main()
16 {
17     const tgh v;
18     tgh s;
19     const int i=s.a();//调用的是int a()
20     int const j=s.a();//调用的是int a()
21     printf("%d,%d",j,i);
22     const int k = v.a();();//调用的是const int a() 
23     cout<<k<<endl;
24     system("pause");
25 }
26 
27 结果是3,35 
posted @ 2012-04-13 15:01 王海光 阅读(373) | 评论 (0)编辑 收藏
相关文章链接:

http://special.csdn.net/mongodb/
http://www.cnblogs.com/fish-li/archive/2011/06/26/2090800.html#_labelStart


Hadoop

一个分布式系统基础架构,由Apache基金会开发。用户可以在不了解分布式底层细节的情况下,开发分布式程序。充分利用集群的威力高速运算和存储。Hadoop实现了一个分布式文件系统(Hadoop Distributed File System),简称HDFS。HDFS有着高容错性的特点,并且设计用来部署在低廉的(low-cost)硬件上。而且它提供高传输率(high throughput)来访问应用程序的数据,适合那些有着超大数据集(large data set)的应用程序。HDFS放宽了(relax)POSIX的要求(requirements)这样可以流的形式访问(streaming access)文件系统中的数据。


joomla

(Content Management System, CMS),它属于Portal(企业入口网站)类型,顾名思义,就是比较适合作为商业类型的网站程序。一般人对这类型的内容管理系统可能会有以下的别名来称呼:
  ■ 架站程序(或软件
  ■ 快速架站程序(或软件)
  ■ 整站程序
posted @ 2012-04-13 12:35 王海光 阅读(473) | 评论 (0)编辑 收藏
本文转自:http://www.cppblog.com/humanchao/archive/2008/07/24/57063.html

学习数据结构和算法的好东西,非常形象,制作水平比较高,向制作者致敬!里面包含以下算法的过程演示:

B树的删除
B树的生长过程
三元组表的转置
中序线索化二叉树
串的顺序存储
二分查找
二叉排序树的删除
二叉排序树的生成
二叉树的建立
克鲁斯卡尔算法构造最小生成树
冒泡排序
分块查找
单链表结点的删除
单链表结点的插入
图的深度优先遍历
基数排序
堆排序
头插法建单链表
寻找中序线索化二叉树指定结点的前驱
寻找中序线索化二叉树指定结点的后继
尾插法建表
希儿排序
开放定址法建立散列表
循环队列操作演示
快速排序
拉链法创建散列表
拓扑排序
数据结构和算法Flash动画演示.rar
最短路径
朴素串匹配算法过程示意
构造哈夫曼树的算法模拟
构造哈夫曼树过程
栈与递归
...更多

点击下载
posted @ 2012-04-13 12:05 王海光 阅读(636) | 评论 (0)编辑 收藏
本文转自:http://www.cppblog.com/humanchao/archive/2008/07/02/55154.html


#import   
"scrrun.dll"   raw_interfaces_only

// 参数格式:"c:\" 或 "c:\test"
ULONGLONG GetPathUseSpace(
const char *szPath)
{
    ASSERT(szPath 
!= NULL);

    
int nLen = strlen(szPath);
    
if (nLen == 0)
        
return 0;

    ULONGLONG result 
= 0;

    
if (nLen == 3)      // c:\
    {
        ULARGE_INTEGER nFreeBytesAvailable;
        ULARGE_INTEGER nTotalNumberOfBytes;
        ULARGE_INTEGER nTotalNumberOfFreeBytes;
        
//
        if (GetDiskFreeSpaceEx(szPath,
              
&nFreeBytesAvailable,
              
&nTotalNumberOfBytes,
              
&nTotalNumberOfFreeBytes))
        {
            result 
= nTotalNumberOfBytes.QuadPart - nFreeBytesAvailable.QuadPart;
        }
    }
    
else
    {
        CoInitialize(NULL);  
        {  
            
try  
            {  
                Scripting::IFileSystem3Ptr   fs;  
                fs.CreateInstance(__uuidof(Scripting::FileSystemObject)); 
                
                Scripting::IFolderPtr   folder;  
                fs
->GetFolder(_bstr_t(szPath),&folder);
                
                _variant_t vsize;
                folder
->get_Size(&vsize);
                result 
= (double)vsize;
            }  
            
catch(_com_error &e)  
            {  
                result 
= -1;
            }  
        }  

        CoUninitialize();   
    }

    
return result;
}

Scrrun.dll枚举文件
CoInitialize(NULL); 

    
try 
    {  
        Scripting::IFileCollectionPtr   files; 
        folder
-> get_Files(&files); 
        
long   count   =   0
        files
-> get_Count(&count); 
        cout 
< < "files   count: " < <count < <endl; 
        IUnknown   
*pUnk=NULL; 
        HRESULT   hr   
=   files-> get__NewEnum(&pUnk); 
        
if(SUCCEEDED(hr)) 
        { 
            CComPtr 
<IEnumVARIANT>   pEnum; 
            hr   
=   pUnk-> QueryInterface(IID_IEnumVARIANT,(void**)&pEnum); 
            
if(pEnum) 
            { 
                pEnum
-> Reset(); 
                ULONG   fget   
=   1
                
while(SUCCEEDED(hr)&&fget> 0
                { 
                    Scripting::IFilePtr   file; 
                    _variant_t   varfile; 
                    hr   
=   pEnum-> Next(1,&varfile,&fget); 
                    
if(SUCCEEDED(hr)   &&   fget> 0
                    { 
                        file   
=              varfile.pdispVal; 
                        BSTR   bspath; 
                        file
-> get_Path(&bspath); 
                        cout 
< < "file   path: " < <(LPCTSTR)_bstr_t(bspath) < <endl; 
                    } 
                    
else 
                    { 
                        cout 
< < "   get   file     return   " < <hr < <endl; 
                    } 
                } 
            } 
        } 
    } 
    
catch(_com_error   &e) 
    { 
         _bstr_t   bstrSource(e.Source()); 
         _bstr_t   bstrDescription(e.Description()); 
          cout 
< < "Get   directory    size   via   FileSystemObject,   by    masterz " < <endl; 
          cout 
< < "COM   error    occurred,source: " < <(LPCTSTR)bstrSource < <endl; 
          cout 
< < "Description: " < <(LPCTSTR)bstrDescription < <endl; 
    } 

CoUninitialize();
posted @ 2012-04-13 09:33 王海光 阅读(776) | 评论 (0)编辑 收藏
本文转自:http://www.cppblog.com/humanchao/archive/2008/07/23/56962.html

如果BAT不带参数,脚本内容如下:

SetOutPath '$INSTDIR'
ExecWait '$INSTDIR\A.bat'

如果BAT需要参数时,要把带参数的命令写入另外一个新的BAT中,执行新BAT:

B.bat内容:
CALL A.bat install

NSIS 脚本:
SetOutPath '$INSTDIR'
ExecWait '$INSTDIR\B.bat'
posted @ 2012-04-12 13:00 王海光 阅读(980) | 评论 (0)编辑 收藏
本文转自:http://www.cppblog.com/humanchao/archive/2008/08/19/59309.html

我们先看一个函数:函数的功能完成1~10的加法。

int Add1to10(int a, int b)
{
   
return a +b;
}

但是一般我们还需要加上几条代码:

int Add1to10(int a, int b)
{
    assert(a 
>= 1 && a <= 10);
    assert(b 
>= 1 && b < =10);

    
if ( a < 1 || a > 10 || b < 1 || b > 10)
        
return -1;

    
return a +b;
}

加上上面几条代码的作用是检查函数的输入参数,当参数不正确的时候不光要在返回值上得到体现,而且会触发assert断言,提醒我们参数有误。

断言式编程体现一个编程的思想,在我们的程序执行偏离预想的路线时给出提醒。当程序执行偏离预想的路线时一般会出现两种可能:即断言以上的程序没有理解下面程序的调用条件、或断言以下的程序需要接受更为宽泛输入条件。以下分别讨论修改方法:

1、如果函数的输入参数是我们编程的一个疏漏,我们认为根本就不应该出现或产生这样的值,那我们应该修改调用函数处的代码,避免非预想的值出现。

2、如果无法避免出现或者产生一个非法输入值,那我们要么在函数调用处加入判断,产生符合条件的值时调用函数,不符合参数条件else处理;要么修改函数,使函数可以接受更为宽泛输入条件,并调整断言内容和参数判断逻辑。

断言不仅可以出现在函数的参数检查的场合,也可以出现在其他的上下文调用的场合。而且它还会随着程序的开发进程逐渐的增加、删除和调整。它可以验证程序是按照我们预想的思路在执行,当出现意外时及时的给出提醒,提醒我们修正程序或者自己的思路。
posted @ 2012-04-12 12:58 王海光 阅读(622) | 评论 (0)编辑 收藏
仅列出标题
共27页: First 19 20 21 22 23 24 25 26 27