Win32 API 封装类总结_demo_01_createchildwindow.c-程序员宅基地

技术标签: 转载  VC++  win32 api  win32 api 封装类  win32 api dNet封装类  .Net  

以下是一些封装的Win32 API类;备用;


重温WIN32 API ------ 最简单的Windows窗口封装类

http://blog.csdn.net/smstong/article/details/42366899


1 开发语言抉择
 1.1 关于开发Win32 程序的语言选择 C还是C++
在决定抛弃MFC,而使用纯Win32 API 开发Window桌面程序之后,还存在一个语言的选择,这就是是否使用C++。C++作为C的超集,能实现所有C能实现的功能。其实反之亦然,C本身也能完成C++超出的那部分功能,只是可能需要更多行的代码。就本人理解而言,
对于巨大型项目,还是使用纯C来架构更加稳妥;
对于中小型项目来说,C++可能更方便快捷。由于目前做的是中小项目,所以决定把C++作为主要开发语言。
 1.2 关于C++特性集合的选择
在决定使用C++之后,还有一个至关重要的抉择,那就是C++特性集合的选择。C++实在是太复杂了,除了支持它的老祖先C的所有开发模式,还支持基于对象开发(OB)、面向对象开发(OO)、模板技术。可以说,C++是个真正全能型语言,这同时也造成了C++的高度复杂


性。使用不同的开发模式,就相当于使用不同的编程语言。就本人而言,对C++的模板编程也根本没有任何经验。综合过去的经验教训和本人对C++的掌握程度,决定:
使用基于对象和面向对象两种开发模式,如果一个功能两种都可以实现,则优先选择基于对象。倾向于OB的技术观点来自对苹果Object-C开发经验。
尽量避免多继承,此观点来自Java和.net开发经验。
数据结构和容器,使用C++标准模板库(STL),模板编程本身复杂,但是使用STL却非常容易。
2 Windows窗口对象的封装类
对Windows桌面程序而言,Window和Message的概念是核心。首先需要封装的就是窗口,例如MFC就是用CWnd类封装了窗口对象。我们当初抛弃MFC的原因,就是因为它太复杂不容易理解,所以对基本窗口对象的封装一定要做到最简单化。
2.1 封装原则
首要的原则就是“简单”。能用一个Win32API直接实现的功能,绝不进行二次包装,如移动窗口可以使用 MoveWindow()一个函数实现,类中就不要出现同样功能的MoveWindow()函数。MFC里有很多这种重复的功能,其实只是可以少写一个hwnd参数而已,却多加了一层


调用。我就是要让HWND句柄到处出现,绝不对其隐藏,因为这个概念对于Windows来说太重要了,开发者使用任何封装类都不应该对其视而不见。
 
其次,同样功能多种技术可以实现时,优先选择容易理解的技术,“可理解性”比“运行效率”更重要。
2.2 源码
头文件 XqWindow.h

#pragma once  
#include <vector>  
  
class XqWindow  
{  
public:  
    XqWindow(HINSTANCE hInst);  
    ~XqWindow();  
private:  
    HWND hWnd;    // 对外只读,确保安全  
    HINSTANCE hInstance;  
public:  
    // 返回窗口对象句柄  
    HWND GetHandle();  
    // 消息处理。需要后续默认处理则需要返回0;停止该消息后续处理,则返回1  
    virtual int HandleMessage(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);  
private:  
    // 原始窗口过程  
    static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);  
private:  
    // 已注册过的类集合  
    static std::vector<void*> registeredClassArray;  
public:  
    // 创建窗口  
    void Create();  
};  

XqWindow.cpp

#include "stdafx.h"  
#include "XqWindow.h"  
  
std::vector<void*> XqWindow::registeredClassArray;  
  
// 创建窗口  
void XqWindow::Create()  
{  
    wchar_t szClassName[32];  
    wchar_t szTitle[128];  
    void* _vPtr = *((void**)this);  
    ::wsprintf(szClassName, L"%p", _vPtr);  
  
    std::vector<void*>::iterator it;  
    for (it = registeredClassArray.begin(); it != registeredClassArray.end(); it++)  // 判断对象的类是否注册过  
    {  
        if ((*it) == _vPtr)  
            break;  
    }  
    if (it == registeredClassArray.end())                // 如果没注册过,则进行注册  
    {  
        //注册窗口类  
        WNDCLASSEX wcex;  
        wcex.cbSize = sizeof(WNDCLASSEX);  
        wcex.style = CS_HREDRAW | CS_VREDRAW;  
        wcex.lpfnWndProc = XqWindow::WndProc;  
        wcex.cbClsExtra = 0;  
        wcex.cbWndExtra = 0;  
        wcex.hInstance = this->hInstance;  
        wcex.hIcon = NULL;  
        wcex.hCursor = ::LoadCursor(NULL, IDC_ARROW);  
        wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);  
        wcex.lpszMenuName = NULL;  
        wcex.lpszClassName = szClassName;  
        wcex.hIconSm = NULL;  
        if (0 != ::RegisterClassEx(&wcex))     // 把注册成功的类加入链表  
        {  
            registeredClassArray.push_back(_vPtr);  
        }  
    }  
      
    // 创建窗口  
    if (this->hWnd == NULL)  
    {  
        ::wsprintf(szTitle, L"窗口类名(C++类虚表指针):%p", _vPtr);  
        HWND hwnd = ::CreateWindow(szClassName,  
            szTitle,  
            WS_OVERLAPPEDWINDOW,  
            0, 0, 800, 600,  
            NULL,  
            NULL,  
            hInstance,  
            (LPVOID)this  
            );  
        if (hwnd == NULL)  
        {  
            this->hWnd = NULL;  
            wchar_t msg[100];  
            ::wsprintf(msg, L"CreateWindow()失败:%ld", ::GetLastError());  
            ::MessageBox(NULL, msg, L"错误", MB_OK);  
            return;  
        }  
    }  
}  
XqWindow::XqWindow(HINSTANCE hInst)  
{  
    this->hWnd = NULL;  
    this->hInstance = hInst;  
}  
  
XqWindow::~XqWindow()  
{  
    if ( this->hWnd!=NULL && ::IsWindow(this->hWnd) ) // C++对象被销毁之前,销毁窗口对象  
    {  
        ::DestroyWindow(this->hWnd);  // Tell system to destroy hWnd and Send WM_DESTROY to wndproc  
    }  
}  
  
HWND XqWindow::GetHandle()  
{  
    return this->hWnd;  
}  
// 消息处理。需要后续默认处理则需要返回0;停止该消息后续处理,则返回1  
int XqWindow::HandleMessage(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)  
{  
    return 0;  
}  
  
// 原始窗口过程  
LRESULT CALLBACK XqWindow::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)  
{  
    XqWindow* pObj = NULL;  
    if (message == WM_CREATE)   // 在此消息收到时,把窗口对象句柄赋给C++对象成员,同时把C++对象地址赋给窗口对象成员  
    {  
        pObj = (XqWindow*)(((LPCREATESTRUCT)lParam)->lpCreateParams);  
        pObj->hWnd = hWnd;                                            // 在此处获取HWND,此时CreateWindow()尚未返回。  
        ::SetWindowLong(hWnd, GWL_USERDATA, (LONG)pObj);             // 通过USERDATA把HWND和C++对象关联起来  
    }  
    pObj = (XqWindow*)::GetWindowLong(hWnd, GWL_USERDATA);  
  
    switch (message)  
    {  
    case WM_CREATE:  
        pObj->HandleMessage(hWnd, message, wParam, lParam);  
        break;  
    case WM_DESTROY:  
        if (pObj != NULL)  // 此时,窗口对象已经销毁,通过设置hWnd=NULL,来通知C++对象  
        {  
            pObj->hWnd = NULL;  
        }  
        break;  
    default:  
        pObj = (XqWindow*)::GetWindowLong(hWnd, GWL_USERDATA);  
        if (pObj != NULL)  
        {  
            if (pObj->HandleMessage(hWnd, message, wParam, lParam) == 0) // 调用子类的消息处理虚函数  
            {  
                return DefWindowProc(hWnd, message, wParam, lParam);  
            }  
        }  
        else  
        {  
            return DefWindowProc(hWnd, message, wParam, lParam);  
        }  
        break;  
    }  
    return 0;  
}

2.3 使用举例
 基本用法为,创建一个TestWindow类,继承自XqWindow,然后重新虚函数 HandleMessage()。所有业务处理代码都要在HandleMessage()里调用,由于该函数是成员函数,所有里面可以直接使用this来引用TestWindow类对象的成员。一个例子代码如下:

TestWindow.h

TestWindow.cpp

#pragma once  
#include "XqWindow.h"  
class TestWindow :  
 public XqWindow  
{  
public:  
 TestWindow(HINSTANCE);  
 ~TestWindow();  
protected:  
 int HandleMessage(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);  
private:  
 // 业务数据部分  
 int rectWidth;    
 int rectHeight;  
};  

#include "stdafx.h"  
#include "TestWindow.h"

TestWindow::TestWindow(HINSTANCE hInst) :XqWindow(hInst)  
{  
 rectWidth = 300;  
 rectHeight = 200;  
}

TestWindow::~TestWindow()  
{  
}  
int TestWindow::HandleMessage(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)  
{  
 PAINTSTRUCT ps;  
 HDC hdc;  
 switch (message)  
 {  
 case WM_PAINT:  
  hdc = ::BeginPaint(hWnd, &ps);  
  ::Rectangle(hdc, 0, 0, this->rectWidth, this->rectHeight);  
  ::EndPaint(hWnd, &ps);  
  return 1;  
 default:  
  break;  
 }  
 return 0;  
}  

调用部分:

pTest = new TestWindow(theApp.m_hInstance);  
pTest->Create();  
::ShowWindow(pTest->GetHandle(), SW_SHOW);  
::UpdateWindow(pTest->GetHandle()); 

运行效果:


2.4 技术要点
这个XqWindow类对窗口对象做了最小的封装,主要实现了消息处理函数和C++对象的关联。内存布局如下:
 
需要说明的几点:
(1)C++类和窗口类的一一对应。由于VC++默认不启用RTTI,同时考虑到代码兼容性和运行效率,也不提倡启用RTTI,在没有RTTI支持的情况下,如何才能在运行时把同一个类的所有实例与其他类的实例进行区分呢?这里我们采用了C++的虚表指针,每一个有虚函数的类


都拥有自己独立的虚表,而这个虚表指针又在每个实例中存储。同一个类的不同实例共享一个虚表,所以这给了我们区分对象所属C++类的机会。当然这种技术只能用到有虚函数的类中,对于没有虚函数的类的对象,不存在虚表。对于我们的情况,XqWindow类有一个


HandleMessage虚函数,从而其他所有继承此类的子类孙类也就都有自己的虚表了。
 
在RegisterClass()之前,首先判断当前C++对象所属类的虚表指针是否存在vptrAraay链表中。如果没有,则注册窗口类,并把虚表指针存放到vptrArray链表中;如果存在,则直接使用该虚表指针对应的窗口类。
 
需要注意的是,获取对象虚表指针值的操作不能在XqWindow::XqWindow()构造函数里进行,因为在执行此函数时,C++对象的虚表指针成员尚未被设置到指向派生类的虚表地址(因为尚未调用子类的构造函数)。所以必须在对象构造完成之后才能获取虚表指针值,这也是


为什么Create()不能在XqWindow()构造函数里调用的原因。(我曾经为了简化调用把Create()放到XqWindow()里,导致了所有对象的虚表指针都相同的后果!)
 
(2)C++对象与窗口对象的关系。C++对象创建以后,调用Create()是唯一可以和窗口对象绑定到一起的途径。在旧窗口销毁之前,C++对象不能再创建新窗口,调用Create()多次也没用。
 
C++对象生存寿命也大于对应的窗口寿命,否则窗口过程中使用C++对象就会出现非法访问内存问题。这两种对象的生命序列为: C++ 对象出生 -- 调用Create()产生窗口对象--某种原因窗口对象销毁--C++对象销毁。
为防止C++对象在窗口对象之前销毁,在XqWindow类的析构函数中,先通过DestroyWindow()销毁窗口对象。窗口对象销毁时,也会设置C++对象的hWnd为NULL,来通知C++对象窗口的销毁。
 
形象一点的说法:C++对象和窗口对象则是一夫一妻制、且只能丧偶不能离异条件下的夫妻关系,而且C++对象是寿命长的一方,窗口对象则是寿命短的一方。只有一个窗口对象死掉后,C++对象才能重新生成新窗口。而且C++对象死掉之前,需要先把窗口对象杀死陪葬。
 
(3)C++对象和窗口对象的彼此引用。C++对象通过成员变量hWnd引用窗口对象,窗口对象则通过GWL_USERDATA附加数据块指向C++对象。另外为了及时捕获WM_CRATE消息并在HandleMessage里处理,C++成员hWnd的赋值并没有在CreateWindow()之后,而是在原始窗口过程


函数处理WM_CREAT消息时。这主要与CreateWindow()原理有关。
 
CreateWindow()
{
   HWND hwnd = malloc(..);
   初始化窗口对象;
   WndProc(hwnd, WM_CRATE, ..);  // 此时已经创建了窗口
   其他操作;
   return hwnd;
}
同理,DestroyWindow()的原理为.
DestroyWindow(hwnd)
{
   窗口对象清理工作;
   WndProc(hwnd, WM_DESTROY, ..); // 此时窗口已经不可见了
         其他操作;
   free(hwnd);
}
2.5 存在问题
虽然XqWindow类可以很好的工作,但也存在一些问题:
(1)由于Window对象靠USERDATA引用C++对象,所以如果其他代码通过SetWindowLong(hwnd, GWL_USERDATA, xxx)修改了这个数据块,那么程序将会崩溃。如何防止这种破坏,需要进一步研究。
(2)使用C++对象的虚表指针,而这个指针的具体内存布局并没有明确的规范标准,一旦将来VC++编译器修改虚表指针的存放位置,程序将会出问题。不过由于考虑到二进制的兼容性,VC++作出这种改变的可能性不大。
 
3 一点感受
XqWindow类的源码一共不到150行,却花了我2天的业余时间来完成。这里涉及到对C++对象内存布局,窗口创建、销毁、消息处理过程的深入理解。写一个小小类就如此不易,写一个健壮的类库真是难上加难,想想MFC也真的挺不容易的。

========

重温WIN32 API ------ Window消息跟踪

http://blog.csdn.net/smstong/article/details/42421115


1 探索消息处理过程的必要性与可能性
Windows操作系统的名称本身就是其核心概念--窗口。与窗口密不可分的就是消息了,本文建立一个最简单的Windows窗口程序,然后增加跟踪代码,把所有的Windows消息打印到文件中。我们知道,Windows处理消息的时候是序列化处理的,只有一个线程来完成,所以消


息的处理具有严格的顺序,这也便于我们分析消息处理过程。
运行环境: Windows8.1
编译环境:VS2013
项目源码:见附录
2 消息跟踪结果与分析
2.1 结果文件
由于结果文件太大了,请读者自己编译此项目运行查看,项目源码已放到了文后的附录里。
2.2 分析结论
USER32.dll中的代码和我们编写的代码彼此调用,下面是几个具体的小结论。
(1)当我们调用CreateWindow()创建窗口的时候,这个函数的内部却在以不同参数多次调用我们编写的窗口过程WndProc了;
(2)当我们调用ShowWindow()显示窗口的时候,这个函数内部疯狂地多次以不同参数调用WndProc();
(3)当我们调用UpdateWindow()更新窗口时,这个函数内部以WM_PAINT参数调用WndProc();
(4)当我们调用GetMessage()从消息队列取消息时,这个函数内部可能会多次调用WndProc()来处理Send到消息队列中的消息,处理完sent的消息后,才返回一个posted的消息;
(5)我们在WndProc()里调用了DefWindowProc(),而这个函数内部也会根据处理消息的类型,反过来调用WndProc(),有点像递归调用了,不过每次使用的参数值不同,不会出现死循环;
(6)窗口被销毁后,User32模块内部以WM_DESTROY参数调用WndProc()。
(7)应用程序必须自己主动调用PostQuitMessage()来把WM_QUIT放入消息队列中结束消息循环。
附录 项目源代码
main.cpp

#include <Windows.h>  
#include "LogWriter.h"  
#include "WindowsMessages.h"  
  
LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);  
  
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, wchar_t* szCmdLine, int iCmdShow)  
{  
    LOG(L"程序开始");  
    wchar_t szClassName[] = L"MyWindowClass";  
    // 注册窗口类  
    WNDCLASSEX wcex;  
    wcex.cbSize = sizeof(WNDCLASSEX);  
    wcex.style = CS_HREDRAW | CS_VREDRAW;  
    wcex.lpfnWndProc = WndProc;  
    wcex.cbClsExtra = 0;  
    wcex.cbWndExtra = 0;  
    wcex.hInstance = hInstance;  
    wcex.hIcon = NULL;  
    wcex.hCursor = LoadCursor(NULL, IDC_ARROW);  
    wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);  
    wcex.lpszMenuName = NULL;  
    wcex.lpszClassName = szClassName;  
    wcex.hIconSm = NULL;  
    LOG(L"RegisterClassEx()开始");  
    ::RegisterClassEx(&wcex);  
    LOG(L"RegisterClassEx()返回");  
  
    // 创建窗口  
    LOG(L"CreateWindow()开始");  
    HWND hWnd = CreateWindow(szClassName, L"Windows 消息测试", WS_OVERLAPPEDWINDOW,  
        CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);  
    LOG(L"CreateWindow()返回");  
  
    LOG(L"ShowWindow()开始");  
    ::ShowWindow(hWnd, SW_SHOW);  
    LOG(L"ShowWindow()返回");  
  
    LOG(L"UpdateWindow()开始");  
    ::UpdateWindow(hWnd);  
    LOG(L"UpdateWindow()返回");  
  
    // 开启消息循环, 直到取回WM_QUIT消息,GetMessage()返回0,退出循环  
    MSG msg;  
    BOOL bRet = 0;  
    wchar_t str[256];  
    while (1)  
    {  
        LOG(L"GetMessage()开始");  
        bRet = GetMessage(&msg, NULL, 0, 0);  
        ::wsprintf(str, L"GetMessage()返回,取回消息:%s,对应窗口:%X", get_msg_name(msg.message), msg.hwnd);  
        LOG(str);  
  
        if (bRet == 0)  
        {  
            // 收到了WM_QUIT,退出循环  
            break;  
        }  
        else if (bRet == -1)  
        {  
            // 处理错误  
        }  
        else  
        {  
            TranslateMessage(&msg);  
            LOG(L"DispatchMessage()开始");  
            DispatchMessage(&msg);   // 根据msg.hwnd调用指定窗口过程  
            LOG(L"DispatchMessage()返回");  
        }  
    }  
  
    // 程序结束  
    LOG(L"程序结束");  
    ENDLOG  
    return 0;  
}  
  
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)  
{  
    wchar_t str[128];  
    ::wsprintf(str, L"WndProc被调用开始,消息参数: %s", get_msg_name(message));  
    LOG(str);  
    int r = 0;  
    switch (message)  
    {  
    case WM_CREATE:  
        break;  
    case WM_DESTROY:  
        ::PostQuitMessage(0);   // 窗口销毁后,指示退出消息循环  
        break;  
    default:  
        LOG(L"DefWindowProc()开始");  
        r = ::DefWindowProc(hWnd, message, wParam, lParam);  
        LOG(L"DefWindowProc()返回");  
  
        LOG(L"WndProc返回");  
        return r;  
    }  
    LOG(L"WndProc返回");  
    return 0;  
}  

其他辅助文件的功能包括:打印到文件和根据消息号获得消息名称。这些辅助文件一并列到下面:
LogWriter.h

LogWriter.cpp

#pragma once  
/* 
日志记录类 
功能描述: 
根据当前时间自动生成日志文件名,自动记录日志到日志文件。 
 
日志文件名格式(样例): 
20141219211252255.log 
 
日志内容格式(样例): 
2014年12月19日11时52分55秒,源文件:e:\work\udptest\udptestdlg.cpp,第109行, 这里是要写的日志内容 
 
使用方式: 
此类采用单例模式设计,为使用方便,定义了两个宏供用户调用。样例代码: 
LOG(L"这里是要写的日志内容");  // 记录日志到文件 
ENDLOG  // 程序退出之前调用,关闭日志文件 
*/  
#include <stdio.h>  
class LogWriter  
{  
protected:  
    LogWriter();  
    ~LogWriter();  
private:  
    wchar_t fileName[1024];  
    FILE* fp;  
public:  
    void Log(wchar_t* log);  
public:  
    static LogWriter* GetLogWriter();  
    static void DeleteLogWriter();  
private:  
    static LogWriter* theOnlyLogWriter;  
};  
  
#define LOG(x) \  
{ \  
    wchar_t buffer[2048]; \  
    SYSTEMTIME st; \  
    ::GetLocalTime(&st); \  
    swprintf_s(buffer, L"%04d年%02d月%02d日%02d时%02d分%02d秒,源文件:%s,第%d行, %s\n", \  
    st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond, \  
    TEXT(__FILE__), __LINE__, x); \  
    LogWriter::GetLogWriter()->Log(buffer); \  
}  
  
#define ENDLOG \  
    LogWriter::DeleteLogWriter();  


#include <stdio.h>  
#include "LogWriter.h"  
#include "share.h"  
#include <Windows.h>  
LogWriter* LogWriter::theOnlyLogWriter = NULL;  
  
LogWriter::LogWriter()  
{  
    // determine the log file's name, yyyyMMddhhmmss.log  
    SYSTEMTIME st;  
    ::GetLocalTime(&st);  
    ::swprintf_s(this->fileName, L"%04d%02d%02d%02d%02d%02d.log", st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond);  
    fp = ::_wfsopen(this->fileName, L"w,ccs=UTF-8", _SH_DENYNO); // 以共享读写模式打开日志文件  
}  
  
// 线程安全的写入文件  
void LogWriter::Log(wchar_t* log)  
{  
    if (fp != NULL)  
    {  
        ::fwprintf(this->fp, L"%s", log);  
    }  
}  
LogWriter::~LogWriter()  
{  
    if (this->fp != NULL)  
        ::fclose(fp);  
}  
  
LogWriter* LogWriter::GetLogWriter()  
{  
    if (theOnlyLogWriter == NULL)  
    {  
        theOnlyLogWriter = new LogWriter();  
    }  
    return theOnlyLogWriter;  
}  
  
void LogWriter::DeleteLogWriter()  
{  
    if (theOnlyLogWriter != NULL)  
    {  
        delete theOnlyLogWriter;  
        theOnlyLogWriter = NULL;  
    }  
}

WindowsMessage.h

#pragma once  
#include <Windows.h>  
wchar_t* get_msg_name(int message);  
  
static wchar_t* Messages[] =  
{  
    L"WM_NULL",//0x0000  
    L"WM_CREATE",//0x0001  
    L"WM_DESTROY",//0x0002  
    L"WM_MOVE",//0x0003  
    L"WM_SIZEWAIT",//0x0004  
    L"WM_SIZE",//0x0005  
    L"WM_ACTIVATE",//0x0006  
    L"WM_SETFOCUS",//0x0007  
    L"WM_KILLFOCUS",//0x0008  
    L"WM_SETVISIBLE",//0x0009  
    L"WM_ENABLE",//0x000a  
    L"WM_SETREDRAW",//0x000b  
    L"WM_SETTEXT",//0x000c  
    L"WM_GETTEXT",//0x000d  
    L"WM_GETTEXTLENGTH",//0x000e  
    L"WM_PAINT",//0x000f  
    L"WM_CLOSE",   /* 0x10 */  
    L"WM_QUERYENDSESSION",//0x0011  
    L"WM_QUIT",//0x0012  
    L"WM_QUERYOPEN",//0x0013  
    L"WM_ERASEBKGND",//0x0014  
    L"WM_SYSCOLORCHANGE",//0x0015  
    L"WM_ENDSESSION",//0x0016  
    L"WM_SYSTEMERROR",//0x0017  
    L"WM_SHOWWINDOW",//0x0018  
    L"WM_CTLCOLOR",//0x0019  
    L"WM_WININICHANGE",//0x001a  
    L"WM_DEVMODECHANGE",//0x001b  
    L"WM_ACTIVATEAPP",//0x001c  
    L"WM_FONTCHANGE",//0x001d  
    L"WM_TIMECHANGE",//0x001e  
    L"WM_CANCELMODE",//0x001f  
    L"WM_SETCURSOR",  /* 0x20 */  
    L"WM_MOUSEACTIVATE",//0x0021  
    L"WM_CHILDACTIVATE",//0x0022  
    L"WM_QUEUESYNC",//0x0023  
    L"WM_GETMINMAXINFO",//0x0024  
    L"WM_LOGOFF",//0x0025  
    L"WM_PAINTICON",//0x0026  
    L"WM_ICONERASEBKGND",//0x0027  
    L"WM_NEXTDLGCTL",//0x0028  
    L"WM_ALTTABACTIVE",//0x0029  
    L"WM_SPOOLERSTATUS",//0x002a  
    L"WM_DRAWITEM",//0x002b  
    L"WM_MEASUREITEM",//0x002c  
    L"WM_DELETEITEM",//0x002d  
    L"WM_VKEYTOITEM",//0x002e  
    L"WM_CHARTOITEM",//0x002f  
    L"WM_SETFONT",  /* 0x30 */  
    L"WM_GETFONT",//0x0031  
    L"WM_SETHOTKEY",//0x0032  
    L"WM_GETHOTKEY",//0x0033  
    L"WM_FILESYSCHANGE",//0x0034  
    L"WM_ISACTIVEICON",//0x0035  
    L"WM_QUERYPARKICON",//0x0036  
    L"WM_QUERYDRAGICON",//0x0037  
    L"WM_WINHELP",//0x0038  
    L"WM_COMPAREITEM",//0x0039  
    L"WM_FULLSCREEN",//0x003a  
    L"WM_CLIENTSHUTDOWN",//0x003b  
    L"WM_DDEMLEVENT",//0x003c  
    L"WM_GETOBJECT",//0x003d  
    NULL,//0x003e  
    L"WM_CALCSCROLL",//0x003f  
    L"WM_TESTING",           /* 0x40 */  
    L"WM_COMPACTING",//0x0041  
    L"WM_OTHERWINDOWCREATED",//0x0042  
    L"WM_OTHERWINDOWDESTROYED",//0x0043  
    L"WM_COMMNOTIFY",//0x0044  
    L"WM_MEDIASTATUSCHANGE",//0x0045  
    L"WM_WINDOWPOSCHANGING", /* 0x0046 */  
    L"WM_WINDOWPOSCHANGED", /* 0x0047 */  
    L"WM_POWER",//0x0048  
    L"WM_COPYGLOBALDATA",//0x0049  
    L"WM_COPYDATA",//0x004a  
    L"WM_CANCELJOURNAL",//0x004b  
    L"WM_LOGONNOTIFY",//0x004c  
    L"WM_KEYF1",//0x004d  
    L"WM_NOTIFY",//0x004e  
    L"WM_ACCESS_WINDOW",//0x004f  
    L"WM_INPUTLANGCHANGEREQUEST",/* 0x0050 */  
    L"WM_INPUTLANGCHANGE",//0x0051  
    L"WM_TCARD",//0x0052  
    L"WM_HELP",//0x0053  
    L"WM_USERCHANGED",//0x0054  
    L"WM_NOTIFYFORMAT",//0x0055  
    NULL,//0x0056  
    NULL,//0x0057  
    NULL,//0x0058  
    NULL,//0x0059  
    NULL,//0x005a  
    NULL,//0x005b  
    NULL,//0x005c  
    NULL,//0x005d  
    NULL,//0x005e  
    NULL,//0x005f  
    NULL,/* 0x0060 */  
    NULL,//0x0061  
    NULL,//0x0062  
    NULL,//0x0063  
    NULL,//0x0064  
    NULL,//0x0065  
    NULL,//0x0066  
    NULL,//0x0067  
    NULL,//0x0068  
    NULL,//0x0069  
    NULL,//0x006a  
    NULL,//0x006b  
    NULL,//0x006c  
    NULL,//0x006d  
    NULL,//0x006e  
    NULL,//0x006f  
    L"WM_FINALDESTROY",/* 0x0070 */  
    L"WM_MEASUREITEM_CLIENTDATA",//0x0071  
    L"WM_TASKACTIVATED",//0x0072  
    L"WM_TASKDEACTIVATED",//0x0073  
    L"WM_TASKCREATED",//0x0074  
    L"WM_TASKDESTROYED",//0x0075  
    L"WM_TASKUICHANGED",//0x0076  
    L"WM_TASKVISIBLE",//0x0077  
    L"WM_TASKNOTVISIBLE",//0x0078  
    L"WM_SETCURSORINFO",//0x0079  
    NULL,//0x007a  
    L"WM_CONTEXTMENU",//0x007b  
    L"WM_STYLECHANGING",//0x007c  
    L"WM_STYLECHANGED",//0x007d  
    L"WM_DISPLAYCHANGE",//0x007e  
    L"WM_GETICON",//0x007f  
    L"WM_SETICON",  /* 0x0080 */  
    L"WM_NCCREATE",  /* 0x0081 */  
    L"WM_NCDESTROY",  /* 0x0082 */  
    L"WM_NCCALCSIZE",  /* 0x0083 */  
    L"WM_NCHITTEST",         /* 0x0084 */  
    L"WM_NCPAINT",           /* 0x0085 */  
    L"WM_NCACTIVATE",        /* 0x0086 */  
    L"WM_GETDLGCODE",  /* 0x0087 */  
    L"WM_SYNCPAINT",//0x0088  
    L"WM_SYNCTASK",//0x0089  
    NULL,//0x008a  
    L"WM_KLUDGEMINRECT",//0x008b  
    L"WM_LPKDRAWSWITCHWND",//0x008c  
    NULL,//0x008d  
    NULL,//0x008e  
    NULL,//0x008f  
    NULL,/* 0x0090 */  
    NULL,//0x0091  
    NULL,//0x0092  
    NULL,//0x0093  
    NULL,//0x0094  
    NULL,//0x0095  
    NULL,//0x0096  
    NULL,//0x0097  
    NULL,//0x0098  
    NULL,//0x0099  
    NULL,//0x009a  
    NULL,//0x009b  
    NULL,//0x009c  
    NULL,//0x009d  
    NULL,//0x009e  
    NULL,//0x009f  
    L"WM_NCMOUSEMOVE",  /* 0x00A0 *//* 0x00A0 */  
    L"WM_NCLBUTTONDOWN",  /* 0x00A1 */  
    L"WM_NCLBUTTONUP",  /* 0x00A2 */  
    L"WM_NCLBUTTONDBLCLK", /* 0x00A3 */  
    L"WM_NCRBUTTONDOWN",  /* 0x00A4 */  
    L"WM_NCRBUTTONUP",  /* 0x00A5 */  
    L"WM_NCRBUTTONDBLCLK", /* 0x00A6 */  
    L"WM_NCMBUTTONDOWN",  /* 0x00A7 */  
    L"WM_NCMBUTTONUP",  /* 0x00A8 */  
    L"WM_NCMBUTTONDBLCLK", /* 0x00A9 */  
    NULL,//0x00AA  
    L"WM_NCXBUTTONDOWN",//0x00AB  
    L"WM_NCXBUTTONUP",//0x00AC  
    L"WM_NCXBUTTONDBLCLK",//0x00AD  
    L"WM_NCUAHDRAWCAPTION", /* 0x00AE */  
    L"WM_NCUAHDRAWFRAME", /* 0x00AF */  
    L"EM_GETSEL32",              /* 0x00b0 */ /* 0x00B0 - Win32 
 
    Edit controls */  
    L"EM_SETSEL32",              /* 0x00b1 */  
    L"EM_GETRECT32",             /* 0x00b2 */  
    L"EM_SETRECT32",             /* 0x00b3 */  
    L"EM_SETRECTNP32",           /* 0x00b4 */  
    L"EM_SCROLL32",              /* 0x00b5 */  
    L"EM_LINESCROLL32",          /* 0x00b6 */  
    L"EM_SCROLLCARET32",         /* 0x00b7 */  
    L"EM_GETMODIFY32",           /* 0x00b8 */  
    L"EM_SETMODIFY32",           /* 0x00b9 */  
    L"EM_GETLINECOUNT32",        /* 0x00ba */  
    L"EM_LINEINDEX32",           /* 0x00bb */  
    L"EM_SETHANDLE32",           /* 0x00bc */  
    L"EM_GETHANDLE32",           /* 0x00bd */  
    L"EM_GETTHUMB32",            /* 0x00be */  
    NULL,                       /* 0x00bf */  
    NULL,                       /* 0x00c0 */  
    L"EM_LINELENGTH32",          /* 0x00c1 */  
    L"EM_REPLACESEL32",          /* 0x00c2 */  
    L"EM_SETFONT",                /* 0x00c3 */  
    L"EM_GETLINE32",             /* 0x00c4 */  
    L"EM_LIMITTEXT32",           /* 0x00c5 */  
    L"EM_CANUNDO32",             /* 0x00c6 */  
    L"EM_UNDO32",                /* 0x00c7 */  
    L"EM_FMTLINES32",            /* 0x00c8 */  
    L"EM_LINEFROMCHAR32",        /* 0x00c9 */  
    L"EM_SETWORDBREAK",          /* 0x00ca */  
    L"EM_SETTABSTOPS32",         /* 0x00cb */  
    L"EM_SETPASSWORDCHAR32",     /* 0x00cc */  
    L"EM_EMPTYUNDOBUFFER32",     /* 0x00cd */  
    L"EM_GETFIRSTVISIBLELINE32", /* 0x00ce */  
    L"EM_SETREADONLY32",         /* 0x00cf */  
    L"EM_SETWORDBREAKPROC32",    /* 0x00d0 */  
    L"EM_GETWORDBREAKPROC32",    /* 0x00d1 */  
    L"EM_GETPASSWORDCHAR32",     /* 0x00d2 */  
    L"EM_SETMARGINS32",          /* 0x00d3 */  
    L"EM_GETMARGINS32",          /* 0x00d4 */  
    L"EM_GETLIMITTEXT32",        /* 0x00d5 */  
    L"EM_POSFROMCHAR32",         /* 0x00d6 */  
    L"EM_CHARFROMPOS32",         /* 0x00d7 */  
    L"EM_SETIMESTATUS",//0x00D8  
    L"EM_GETIMESTATUS",//0x00D9  
    L"EM_MSGMAX",//0x00DA  
    NULL,//0x00DB  
    NULL,//0x00DC  
    NULL,//0x00DD  
    NULL,//0x00DE  
    NULL,//0x00DF  
    L"SBM_SETPOS32",             /* 0x00e0 *//* 0x00E0 - Win32 
 
    Scrollbars */  
    L"SBM_GETPOS32",             /* 0x00e1 */  
    L"SBM_SETRANGE32",           /* 0x00e2 */  
    L"SBM_GETRANGE32",           /* 0x00e3 */  
    L"SBM_ENABLE_ARROWS32",      /* 0x00e4 */  
    NULL,//0x00e5  
    L"SBM_SETRANGEREDRAW32",     /* 0x00e6 */  
    NULL,//0x00e7  
    NULL,//0x00e8  
    L"SBM_SETSCROLLINFO32",      /* 0x00e9 */  
    L"SBM_GETSCROLLINFO32",      /* 0x00ea */  
    NULL,//0x00eb  
    NULL,//0x00ec  
    NULL,//0x00ed  
    NULL,//0x00ee  
    NULL,//0x00ef  
    L"BM_GETCHECK32",            /* 0x00f0 *//* 0x00F0 - Win32 
 
    Buttons */  
    L"BM_SETCHECK32",            /* 0x00f1 */  
    L"BM_GETSTATE32",            /* 0x00f2 */  
    L"BM_SETSTATE32",            /* 0x00f3 */  
    L"BM_SETSTYLE32",            /* 0x00f4 */  
    L"BM_CLICK32",               /* 0x00f5 */  
    L"BM_GETIMAGE32",            /* 0x00f6 */  
    L"BM_SETIMAGE32",            /* 0x00f7 */  
    NULL,//0x00f8  
    NULL,//0x00f9  
    NULL,//0x00fa  
    NULL,//0x00fb              
    NULL,//0x00fc  
    NULL,//0x00fd  
    NULL,//0x00fe  
    L"WM_INPUT",//0x00ff  
    L"WM_KEYDOWN",  /* 0x0100 */  
    L"WM_KEYUP",   /* 0x0101 */  
    L"WM_CHAR",   /* 0x0102 */  
    L"WM_DEADCHAR",  /* 0x0103 */  
    L"WM_SYSKEYDOWN",  /* 0x0104 */  
    L"WM_SYSKEYUP",  /* 0x0105 */  
    L"WM_SYSCHAR",  /* 0x0106 */  
    L"WM_SYSDEADCHAR",  /* 0x0107 */  
    L"WM_YOMICHAR",  /* 0x0108 */  
    L"WM_UNICHAR",//0x0109  
    L"WM_CONVERTREQUEST",//0x010a  
    L"WM_CONVERTRESULT",//0x010b  
    L"WM_INTERIM",//0x010c  
    L"WM_IME_STARTCOMPOSITION",//0x010d  
    L"WM_IME_ENDCOMPOSITION",//0x010e  
    L"WM_IME_COMPOSITION",//0x010f  
    L"WM_INITDIALOG",  /* 0x0110 */  
    L"WM_COMMAND",  /* 0x0111 */  
    L"WM_SYSCOMMAND",        /* 0x0112 */  
    L"WM_TIMER",   /* 0x0113 */  
    L"WM_HSCROLL",  /* 0x0114 */  
    L"WM_VSCROLL",  /* 0x0115 */  
    L"WM_INITMENU",              /* 0x0116 */  
    L"WM_INITMENUPOPUP",         /* 0x0117 */  
    L"WM_SYSTIMER",  /* 0x0118 */  
    NULL,//0x0119  
    NULL,//0x011a  
    NULL,//0x011b  
    NULL,//0x011c  
    NULL,//0x011d  
    NULL,//0x011e  
    L"WM_MENUSELECT",            /* 0x011f */  
    L"WM_MENUCHAR",              /* 0x0120 */  
    L"WM_ENTERIDLE",             /* 0x0121 */  
    L"WM_MENURBUTTONUP",//0x0122  
    L"WM_MENUDRAG",//0x0123  
    L"WM_MENUGETOBJECT",//0x0124  
    L"WM_UNINITMENUPOPUP",//0x0125  
    L"WM_MENUCOMMAND",//0x0126  
    L"WM_CHANGEUISTATE",//0x0127  
    L"WM_UPDATEUISTATE",//0x0128  
    L"WM_QUERYUISTATE",//0x0129  
    NULL,//0x012a  
    NULL,//0x012b  
    NULL,//0x012c  
    NULL,//0x012d  
    NULL,//0x012e  
    NULL,//0x012f  
    NULL,/* 0x0130 */  
    L"WM_LBTRACKPOINT",          /* 0x0131 */  
    L"WM_CTLCOLORMSGBOX",        /* 0x0132 */  
    L"WM_CTLCOLOREDIT",          /* 0x0133 */  
    L"WM_CTLCOLORLISTBOX",       /* 0x0134 */  
    L"WM_CTLCOLORBTN",           /* 0x0135 */  
    L"WM_CTLCOLORDLG",           /* 0x0136 */  
    L"WM_CTLCOLORSCROLLBAR",     /* 0x0137 */  
    L"WM_CTLCOLORSTATIC",        /* 0x0138 */  
    NULL,//0x0139  
    NULL,//0x013a  
    NULL,//0x013b  
    NULL,//0x013c  
    NULL,//0x013d  
    NULL,//0x013e  
    NULL,//0x013f  
    L"CB_GETEDITSEL32",          /* 0x0140 *//* 0x0140 - Win32 
 
    Comboboxes */  
    L"CB_LIMITTEXT32",           /* 0x0141 */  
    L"CB_SETEDITSEL32",          /* 0x0142 */  
    L"CB_ADDSTRING32",           /* 0x0143 */  
    L"CB_DELETESTRING32",        /* 0x0144 */  
    L"CB_DIR32",                 /* 0x0145 */  
    L"CB_GETCOUNT32",            /* 0x0146 */  
    L"CB_GETCURSEL32",           /* 0x0147 */  
    L"CB_GETLBTEXT32",           /* 0x0148 */  
    L"CB_GETLBTEXTLEN32",        /* 0x0149 */  
    L"CB_INSERTSTRING32",        /* 0x014a */  
    L"CB_RESETCONTENT32",        /* 0x014b */  
    L"CB_FINDSTRING32",          /* 0x014c */  
    L"CB_SELECTSTRING32",        /* 0x014d */  
    L"CB_SETCURSEL32",           /* 0x014e */  
    L"CB_SHOWDROPDOWN32",        /* 0x014f */  
    L"CB_GETITEMDATA32",         /* 0x0150 */  
    L"CB_SETITEMDATA32",         /* 0x0151 */  
    L"CB_GETDROPPEDCONTROLRECT32",/* 0x0152 */  
    L"CB_SETITEMHEIGHT32",       /* 0x0153 */  
    L"CB_GETITEMHEIGHT32",       /* 0x0154 */  
    L"CB_SETEXTENDEDUI32",       /* 0x0155 */  
    L"CB_GETEXTENDEDUI32",       /* 0x0156 */  
    L"CB_GETDROPPEDSTATE32",     /* 0x0157 */  
    L"CB_FINDSTRINGEXACT32",     /* 0x0158 */  
    L"CB_SETLOCALE32",           /* 0x0159 */  
    L"CB_GETLOCALE32",           /* 0x015a */  
    L"CB_GETTOPINDEX32",         /* 0x015b */  
    L"CB_SETTOPINDEX32",         /* 0x015c */  
    L"CB_GETHORIZONTALEXTENT32", /* 0x015d */  
    L"CB_SETHORIZONTALEXTENT32", /* 0x015e */  
    L"CB_GETDROPPEDWIDTH32",     /* 0x015f */  
    L"CB_SETDROPPEDWIDTH32",     /* 0x0160 */  
    L"CB_INITSTORAGE32",         /* 0x0161 */  
    NULL,//0x0162  
    L"CB_MULTIPLEADDSTRING",//0x0163  
    L"CB_GETCOMBOBOXINFO",//0x0164  
    NULL,//0x0165  
    NULL,//0x0166  
    NULL,//0x0167  
    NULL,//0x0168  
    NULL,//0x0169  
    NULL,//0x016a  
    NULL,//0x016b  
    NULL,//0x016c  
    NULL,//0x016d  
    NULL,//0x016e  
    NULL,//0x016f  
    L"STM_SETICON32",  /* 0x0170 */ /* 0x0170 - Win32 Static 
 
    controls */  
    L"STM_GETICON32",  /* 0x0171 */  
    L"STM_SETIMAGE32",  /* 0x0172 */  
    L"STM_GETIMAGE32",  /* 0x0173 */  
    L"STM_MSGMAX",//0x0174  
    NULL,//0x0175  
    NULL,//0x0176  
    NULL,//0x0177  
    NULL,//0x0178  
    NULL,//0x0179  
    NULL,//0x017a  
    NULL,//0x017b  
    NULL,//0x017c  
    NULL,//0x017d  
    NULL,//0x017e  
    NULL,//0x017f  
    L"LB_ADDSTRING32",           /* 0x0180 *//* 0x0180 - Win32 
 
    Listboxes */  
    L"LB_INSERTSTRING32",        /* 0x0181 */  
    L"LB_DELETESTRING32",        /* 0x0182 */  
    L"LB_SELITEMRANGEEX32",      /* 0x0183 */  
    L"LB_RESETCONTENT32",        /* 0x0184 */  
    L"LB_SETSEL32",              /* 0x0185 */  
    L"LB_SETCURSEL32",           /* 0x0186 */  
    L"LB_GETSEL32",              /* 0x0187 */  
    L"LB_GETCURSEL32",           /* 0x0188 */  
    L"LB_GETTEXT32",             /* 0x0189 */  
    L"LB_GETTEXTLEN32",          /* 0x018a */  
    L"LB_GETCOUNT32",            /* 0x018b */  
    L"LB_SELECTSTRING32",        /* 0x018c */  
    L"LB_DIR32",                 /* 0x018d */  
    L"LB_GETTOPINDEX32",         /* 0x018e */  
    L"LB_FINDSTRING32",          /* 0x018f */  
    L"LB_GETSELCOUNT32",         /* 0x0190 */  
    L"LB_GETSELITEMS32",         /* 0x0191 */  
    L"LB_SETTABSTOPS32",         /* 0x0192 */  
    L"LB_GETHORIZONTALEXTENT32", /* 0x0193 */  
    L"LB_SETHORIZONTALEXTENT32", /* 0x0194 */  
    L"LB_SETCOLUMNWIDTH32",      /* 0x0195 */  
    L"LB_ADDFILE32",             /* 0x0196 */  
    L"LB_SETTOPINDEX32",         /* 0x0197 */  
    L"LB_GETITEMRECT32",         /* 0x0198 */  
    L"LB_GETITEMDATA32",         /* 0x0199 */  
    L"LB_SETITEMDATA32",         /* 0x019a */  
    L"LB_SELITEMRANGE32",        /* 0x019b */  
    L"LB_SETANCHORINDEX32",      /* 0x019c */  
    L"LB_GETANCHORINDEX32",      /* 0x019d */  
    L"LB_SETCARETINDEX32",       /* 0x019e */  
    L"LB_GETCARETINDEX32",       /* 0x019f */  
    L"LB_SETITEMHEIGHT32",       /* 0x01a0 */  
    L"LB_GETITEMHEIGHT32",       /* 0x01a1 */  
    L"LB_FINDSTRINGEXACT32",     /* 0x01a2 */  
    L"LB_CARETON32",             /* 0x01a3 */  
    L"LB_CARETOFF32",            /* 0x01a4 */  
    L"LB_SETLOCALE32",           /* 0x01a5 */  
    L"LB_GETLOCALE32",           /* 0x01a6 */  
    L"LB_SETCOUNT32",            /* 0x01a7 */  
    L"LB_INITSTORAGE32",         /* 0x01a8 */  
    L"LB_ITEMFROMPOINT32",       /* 0x01a9 */  
    L"LB_INSERTSTRINGUPPER",//0x01aa  
    L"LB_INSERTSTRINGLOWER",//0x01ab  
    L"LB_ADDSTRINGUPPER",//0x01ac  
    L"LB_ADDSTRINGLOWER",//0x01ad  
    L"LBCB_STARTTRACK",//0x01ae  
    L"LBCB_ENDTRACK",//0x01af  
    NULL,/* 0x01B0 */  
    L"LB_MULTIPLEADDSTRING",//0x01b1  
    L"LB_GETLISTBOXINFO",//0x01b2  
    NULL,//0x01b3  
    NULL,//0x01b4  
    NULL,//0x01b5  
    NULL,//0x01b6  
    NULL,//0x01b7  
    NULL,//0x01b8  
    NULL,//0x01b9  
    NULL,//0x01ba  
    NULL,//0x01bb  
    NULL,//0x01bc  
    NULL,//0x01bd  
    NULL,//0x01be  
    NULL,//0x01bf  
    NULL,/* 0x01C0 */  
    NULL,//0x01c1  
    NULL,//0x01c2  
    NULL,//0x01c3  
    NULL,//0x01c4  
    NULL,//0x01c5  
    NULL,//0x01c6  
    NULL,//0x01c7  
    NULL,//0x01c8  
    NULL,//0x01c9  
    NULL,//0x01ca  
    NULL,//0x01cb  
    NULL,//0x01cc  
    NULL,//0x01cd  
    NULL,//0x01ce  
    NULL,//0x01cf  
    NULL,/* 0x01D0 */  
    NULL,//0x01d1  
    NULL,//0x01d2  
    NULL,//0x01d3  
    NULL,//0x01d4  
    NULL,//0x01d5  
    NULL,//0x01d6  
    NULL,//0x01d7  
    NULL,//0x01d8  
    NULL,//0x01d9  
    NULL,//0x01da  
    NULL,//0x01db  
    NULL,//0x01dc  
    NULL,//0x01dd  
    NULL,//0x01de  
    NULL,//0x01df  
    NULL,/* 0x01E0 */  
    NULL,//0x01e1  
    NULL,//0x01e2  
    L"MN_SETHMENU",//0x01e3  
    L"MN_GETHMENU",//0x01e4  
    L"MN_SIZEWINDOW",//0x01e5  
    L"MN_OPENHIERARCHY",//0x01e6  
    L"MN_CLOSEHIERARCHY",//0x01e7  
    L"MN_SELECTITEM",//0x01e8  
    L"MN_CANCELMENUS",//0x01e9  
    L"MN_SELECTFIRSTVALIDITEM",//0x01ea  
    NULL,//0x01eb  
    NULL,//0x01ec  
    NULL,//0x01ed  
    L"MN_FINDMENUWINDOWFROMPOINT",//0x01ee  
    L"MN_SHOWPOPUPWINDOW",//0x01ef  
    L"MN_BUTTONUP",//0x01f0  
    L"MN_SETTIMERTOOPENHIERARCHY",//0x01f1  
    L"MN_DBLCLK",//0x01f2  
    L"MN_ACTIVEPOPUP",//0x01f3  
    L"MN_ENDMENU",//0x01f4  
    L"MN_DODRAGDROP",//0x01f5  
    NULL,//0x01f6  
    NULL,//0x01f7  
    NULL,//0x01f8  
    NULL,//0x01f9  
    NULL,//0x01fa  
    NULL,//0x01fb  
    NULL,//0x01fc  
    NULL,//0x01fd  
    NULL,//0x01fe  
    NULL,//0x01ff  
};

WindowsMessages.cpp

#include "WindowsMessages.h"  
  
wchar_t* get_msg_name(int message)  
{  
    static wchar_t str[64];  
    if ( message<0 || message>(sizeof(Messages) / sizeof(wchar_t) ))  
    {  
        wsprintf(str, L"未收录消息:%X", message);  
        return str;  
    }  
    wchar_t* msg = Messages[message];  
    if (msg == NULL)  
    {  
        wsprintf(str, L"不明消息:%X", message);  
        return str;  
    }  
    return msg;  
} 

========

一个Win32 API实例类(代码收集)

http://www.cnblogs.com/wuhenke/archive/2010/04/13/1711380.html
  最近看到别人代码中一个很好的功能类,该类是一个Win32 API实例类,该类功能包括:同一程序禁止启动多次;获取任意窗体;恢复窗体状态;设置窗体焦点等。


该类很实用,与大家分享一下:

//Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/--> 1     /// Summary description for ProcessUtils.
    public static class ProcessUtils
    {
        private static Mutex mutex = null;

        /// Determine if the current process is already running
        public static bool ThisProcessIsAlreadyRunning()
        {
            // Only want to call this method once, at startup.
            Debug.Assert(mutex == null);

            // createdNew needs to be false in .Net 2.0, otherwise, if another instance of
            // this program is running, the Mutex constructor will block, and then throw 
            // an exception if the other instance is shut down.
            bool createdNew = false;

            mutex = new Mutex(false, Application.ProductName, out createdNew);

            Debug.Assert(mutex != null);

            return !createdNew;
        }

        [DllImport("user32.dll", SetLastError = true)]
        static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

        [DllImport("user32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        static extern bool SetForegroundWindow(IntPtr hWnd);

        [DllImport("user32.dll")]
        static extern bool IsIconic(IntPtr hWnd);

        [DllImport("user32.dll")]
        static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);

        const int SW_RESTORE = 9;

        [DllImport("user32.dll")]
        static extern IntPtr GetLastActivePopup(IntPtr hWnd);

        [DllImport("user32.dll")]
        static extern bool IsWindowEnabled(IntPtr hWnd);

        /// Set focus to the previous instance of the specified program.
        public static void SetFocusToPreviousInstance(string windowCaption)
        {
            // Look for previous instance of this program.
            IntPtr hWnd = FindWindow(null, windowCaption);

            // If a previous instance of this program was found...
            if (hWnd != null)
            {
                // Is it displaying a popup window?
                IntPtr hPopupWnd = GetLastActivePopup(hWnd);

                // If so, set focus to the popup window. Otherwise set focus
                // to the program's main window.
                if (hPopupWnd != null && IsWindowEnabled(hPopupWnd))
                {
                    hWnd = hPopupWnd;
                }

                SetForegroundWindow(hWnd);

                // If program is minimized, restore it.
                if (IsIconic(hWnd))
                {
                    ShowWindow(hWnd, SW_RESTORE);
                }
            }
        }
    }

========

常用Win32API 封装 Win32api for .net



http://www.cnblogs.com/me-sa/articles/659925.html

struct Win32
        {
        public const string TOOLBARCLASSNAME = "ToolbarWindow32";

        public const int WS_CHILD = 0x40000000;
        public const int WS_VISIBLE = 0x10000000;
        public const int WS_CLIPCHILDREN = 0x2000000;
        public const int WS_CLIPSIBLINGS = 0x4000000;
        public const int WS_BORDER = 0x800000;
    
        public const int CCS_NODIVIDER = 0x40;
        public const int CCS_NORESIZE = 0x4;
        public const int CCS_NOPARENTALIGN = 0x8;

        public const int I_IMAGECALLBACK = -1;
        public const int I_IMAGENONE = -2;

        public const int TBSTYLE_TOOLTIPS = 0x100;
        public const int TBSTYLE_FLAT = 0x800;
        public const int TBSTYLE_LIST = 0x1000;
        public const int TBSTYLE_TRANSPARENT = 0x8000;

        public const int TBSTYLE_EX_DRAWDDARROWS = 0x1;
        public const int TBSTYLE_EX_HIDECLIPPEDBUTTONS = 0x10;
        public const int TBSTYLE_EX_DOUBLEBUFFER = 0x80;
    
        public const int CDRF_DODEFAULT = 0x0;
        public const int CDRF_SKIPDEFAULT = 0x4;
        public const int CDRF_NOTIFYITEMDRAW = 0x20;
        public const int CDDS_PREPAINT = 0x1;
        public const int CDDS_ITEM = 0x10000;
        public const int CDDS_ITEMPREPAINT = CDDS_ITEM | CDDS_PREPAINT;

        public const int CDIS_HOT = 0x40;
        public const int CDIS_SELECTED = 0x1;
        public const int CDIS_DISABLED = 0x4;
    
        public const int WM_SETREDRAW = 0x000B;
        public const int WM_CANCELMODE = 0x001F;
        public const int WM_NOTIFY = 0x4e;
        public const int WM_KEYDOWN = 0x100;
        public const int WM_KEYUP = 0x101;
        public const int WM_CHAR = 0x0102;
        public const int WM_SYSKEYDOWN = 0x104;
        public const int WM_SYSKEYUP = 0x105;
        public const int WM_COMMAND = 0x111;
        public const int WM_MENUCHAR = 0x120;
        public const int WM_MOUSEMOVE = 0x200;
        public const int WM_LBUTTONDOWN = 0x201;
        public const int WM_MOUSELAST = 0x20a;
        public const int WM_USER = 0x0400;
        public const int WM_REFLECT = WM_USER + 0x1c00;

        public const int NM_CUSTOMDRAW = -12;    

        public const int TTN_NEEDTEXTA = ((0-520)-0);
        public const int TTN_NEEDTEXTW = ((0-520)-10);

        public const int TBN_QUERYINSERT = ((0-700)-6);
        public const int TBN_DROPDOWN = ((0-700)-10);
        public const int TBN_HOTITEMCHANGE = ((0 - 700) - 13);

        public const int TBIF_IMAGE = 0x1;
        public const int TBIF_TEXT = 0x2;
        public const int TBIF_STATE = 0x4;
        public const int TBIF_STYLE = 0x8;
        public const int TBIF_COMMAND = 0x20;

        public const int MNC_EXECUTE = 2;

        [StructLayout(LayoutKind.Sequential, Pack = 1)]
        public class INITCOMMONCONTROLSEX 
            {
            public int dwSize = 8;
            public int dwICC;
            }

        public const int ICC_BAR_CLASSES = 4;
        public const int ICC_COOL_CLASSES = 0x400;

        [DllImport("comctl32.dll")]
        public static extern bool InitCommonControlsEx(INITCOMMONCONTROLSEX icc);

        [StructLayout(LayoutKind.Sequential)]
        public struct POINT
            {
            public int x;
            public int y;
            }

        [StructLayout(LayoutKind.Sequential)]
        public struct RECT
            {
            public int left;
            public int top;
            public int right;
            public int bottom;
            }

        [StructLayout(LayoutKind.Sequential)]
        public struct NMHDR
            {
            public IntPtr hwndFrom;
            public int idFrom;
            public int code;
            }

        [StructLayout(LayoutKind.Sequential)]
        public struct NMTOOLBAR
            {
            public NMHDR hdr;
            public int iItem;
            public TBBUTTON tbButton;
            public int cchText;
            public IntPtr pszText;
            }
    
        [StructLayout(LayoutKind.Sequential)]
        public struct NMCUSTOMDRAW
            {
            public NMHDR hdr;
            public int dwDrawStage;
            public IntPtr hdc;
            public RECT rc;
            public int dwItemSpec;
            public int uItemState;
            public int lItemlParam;
            }
    
        [StructLayout(LayoutKind.Sequential)]
        public struct LPNMTBCUSTOMDRAW
            {
            public NMCUSTOMDRAW nmcd;
            public IntPtr hbrMonoDither;
            public IntPtr hbrLines;
            public IntPtr hpenLines;
            public int clrText;
            public int clrMark;
            public int clrTextHighlight;
            public int clrBtnFace;
            public int clrBtnHighlight;
            public int clrHighlightHotTrack;
            public RECT rcText;
            public int nStringBkMode;
            public int nHLStringBkMode;
            }

        public const int TTF_RTLREADING = 0x0004;
    
        [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)]
        public struct TOOLTIPTEXT
            {
            public NMHDR hdr;
            public IntPtr lpszText;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst=80)]
            public string szText;
            public IntPtr hinst;
            public int uFlags;
            }

        [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
        public struct TOOLTIPTEXTA
            {
            public NMHDR hdr;
            public IntPtr lpszText;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst=80)]
            public string szText;
            public IntPtr hinst;
            public int uFlags;
            }

        public const int TB_PRESSBUTTON = WM_USER + 3;    
        public const int TB_INSERTBUTTON = WM_USER + 21;
        public const int TB_BUTTONCOUNT = WM_USER + 24;
        public const int TB_GETITEMRECT = WM_USER + 29;
        public const int TB_BUTTONSTRUCTSIZE = WM_USER + 30;    
        public const int TB_SETBUTTONSIZE = WM_USER + 32;
        public const int TB_SETIMAGELIST = WM_USER + 48;
        public const int TB_GETRECT = WM_USER + 51;
        public const int TB_SETBUTTONINFO = WM_USER + 64;
        public const int TB_HITTEST = WM_USER +69;
        public const int TB_GETHOTITEM = WM_USER + 71;
        public const int TB_SETHOTITEM = WM_USER + 72;
        public const int TB_SETEXTENDEDSTYLE = WM_USER + 84;

        public const int TBSTATE_CHECKED = 0x01;
        public const int TBSTATE_ENABLED = 0x04;
        public const int TBSTATE_HIDDEN = 0x08;
    
        public const int BTNS_BUTTON = 0;
        public const int BTNS_SEP = 0x1;
        public const int BTNS_DROPDOWN = 0x8;    
        public const int BTNS_AUTOSIZE = 0x10;
        public const int BTNS_WHOLEDROPDOWN = 0x80;

        [StructLayout(LayoutKind.Sequential, Pack=1)]
        public struct TBBUTTON 
            {
            public int iBitmap;
            public int idCommand;
            public byte fsState;
            public byte fsStyle;
            public byte bReserved0;
            public byte bReserved1;
            public int dwData;
            public int iString;
            }

        [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)]
        public struct TBBUTTONINFO
            {
            public int cbSize;
            public int dwMask;
            public int idCommand;
            public int iImage;
            public byte fsState;
            public byte fsStyle;
            public short cx;
            public IntPtr lParam;
            public IntPtr pszText;
            public int cchText;
            }

        [DllImport("user32.dll", ExactSpelling=true, CharSet=CharSet.Auto)]
        public static extern IntPtr GetParent(IntPtr hWnd);

        [DllImport("user32.dll", CharSet=CharSet.Auto)]
        public static extern int SendMessage(IntPtr hWnd, int msg, int wParam, int lParam);

        [DllImport("user32.dll", CharSet=CharSet.Auto)]
        public static extern IntPtr SendMessage(IntPtr hWnd, int msg, int wParam, IntPtr lParam);

        [DllImport("user32.dll", CharSet=CharSet.Auto)]
        public static extern void SendMessage(IntPtr hWnd, int msg, int wParam, ref RECT lParam);

        [DllImport("user32.dll", CharSet=CharSet.Auto)]
        public static extern int SendMessage(IntPtr hWnd, int msg, int wParam, ref POINT lParam);

        [DllImport("user32.dll", CharSet=CharSet.Auto)]
        public static extern void SendMessage(IntPtr hWnd, int msg, int wParam, ref TBBUTTON lParam);
    
        [DllImport("user32.dll", CharSet=CharSet.Auto)]
        public static extern void SendMessage(IntPtr hWnd, int msg, int wParam, ref TBBUTTONINFO lParam);

        [DllImport("user32.dll", CharSet=CharSet.Auto)]
        public static extern void SendMessage(IntPtr hWnd, int msg, int wParam, ref REBARBANDINFO lParam);
    
        [DllImport("user32.dll", CharSet=CharSet.Auto)]
        public static extern IntPtr PostMessage(IntPtr hWnd, int msg, int wParam, int lParam);
    
        [DllImport("kernel32.dll", ExactSpelling=true, CharSet=CharSet.Auto)]
        public static extern int GetCurrentThreadId();

        public delegate IntPtr HookProc(int nCode, IntPtr wParam, IntPtr lParam);
    
        public const int WH_MSGFILTER = -1;
        public const int MSGF_MENU = 2;
        
        [DllImport("user32.dll", CharSet=CharSet.Auto)]
        public static extern IntPtr SetWindowsHookEx(int hookid, HookProc pfnhook, IntPtr hinst, int threadid);
        
        [DllImport("user32.dll", CharSet=CharSet.Auto, ExactSpelling=true)]
        public static extern bool UnhookWindowsHookEx(IntPtr hhook);
    
        [DllImport("user32.dll", CharSet=CharSet.Auto, ExactSpelling=true)]
        public static extern IntPtr CallNextHookEx(IntPtr hhook, int code, IntPtr wparam, IntPtr lparam);
    
        [StructLayout(LayoutKind.Sequential)]
        public struct MSG 
            {
            public IntPtr hwnd;
            public int message;
            public IntPtr wParam;
            public IntPtr lParam;
            public int time;
            public int pt_x;
            public int pt_y;
            }

        public const string REBARCLASSNAME = "ReBarWindow32";        
    
        public const int RBS_VARHEIGHT = 0x200;
        public const int RBS_BANDBORDERS = 0x400;
        public const int RBS_AUTOSIZE = 0x2000;
    
        public const int RBN_FIRST = -831;
        public const int RBN_HEIGHTCHANGE = RBN_FIRST - 0;
        public const int RBN_AUTOSIZE = RBN_FIRST - 3;
        public const int RBN_CHEVRONPUSHED = RBN_FIRST - 10;
    
        public const int RB_SETBANDINFO = WM_USER + 6;
        public const int RB_GETRECT = WM_USER + 9;
        public const int RB_INSERTBAND = WM_USER + 10;
        public const int RB_GETBARHEIGHT = WM_USER + 27;
    
        [StructLayout(LayoutKind.Sequential)]
        public struct REBARBANDINFO
            {
            public int cbSize;
            public int fMask;
            public int fStyle;
            public int clrFore;
            public int clrBack;
            public IntPtr lpText;
            public int cch;
            public int iImage;
            public IntPtr hwndChild;
            public int cxMinChild;
            public int cyMinChild;
            public int cx;
            public IntPtr hbmBack;
            public int wID;
            public int cyChild;
            public int cyMaxChild;
            public int cyIntegral;
            public int cxIdeal;
            public int lParam;
            public int cxHeader;
            }

        public const int RBBIM_CHILD = 0x10;
        public const int RBBIM_CHILDSIZE = 0x20;
        public const int RBBIM_STYLE = 0x1;
        public const int RBBIM_ID = 0x100;
        public const int RBBIM_SIZE = 0x40;
        public const int RBBIM_IDEALSIZE = 0x200;
        public const int RBBIM_TEXT = 0x4;
    
        public const int RBBS_BREAK = 0x1;
        public const int RBBS_CHILDEDGE = 0x4;
        public const int RBBS_FIXEDBMP = 0x20;
        public const int RBBS_GRIPPERALWAYS = 0x80;
        public const int RBBS_USECHEVRON = 0x200;

        [StructLayout(LayoutKind.Sequential)]
        public struct NMREBARCHEVRON
            {
            public NMHDR hdr;
            public int uBand;
            public int wID;
            public int lParam;
            public RECT rc;
            public int lParamNM;
            }

        [StructLayout(LayoutKind.Sequential)]
        public struct IMAGELISTDRAWPARAMS 
            {
            public int cbSize;
            public IntPtr himl;
            public int i;
            public IntPtr hdcDst;
            public int x;
            public int y;
            public int cx;
            public int cy;
            public int xBitmap;
            public int yBitmap;
            public int rgbBk;
            public int rgbFg;
            public int fStyle;
            public int dwRop;
            public int fState;
            public int Frame;
            public int crEffect;                
            }

        public const int ILD_TRANSPARENT = 0x1;
        public const int ILS_SATURATE = 0x4;

        [DllImport("comctl32.dll", CharSet=CharSet.Auto)]
        public static extern bool ImageList_DrawIndirect(ref IMAGELISTDRAWPARAMS pimldp);
        
        [StructLayout(LayoutKind.Sequential)]
        public struct DLLVERSIONINFO
            {
            public int cbSize;
            public int dwMajorVersion;
            public int dwMinorVersion;
            public int dwBuildNumber;
            public int dwPlatformID;
            }
            
        [DllImport("comctl32.dll")]
        public extern static int DllGetVersion(ref DLLVERSIONINFO dvi);

        public const int SPI_GETFLATMENU = 0x1022;

        [DllImport("user32.dll", CharSet=CharSet.Auto)]
        public extern static int SystemParametersInfo(int nAction, int nParam, ref int value, int ignore);

        public const int DT_SINGLELINE = 0x20;
        public const int DT_LEFT = 0x0;
        public const int DT_VCENTER = 0x4;
        public const int DT_CALCRECT = 0x400;

        [DllImport("user32.dll")]
        public extern static int DrawText(IntPtr hdc, string lpString, int nCount, ref RECT lpRect, int uFormat);

        public const int TRANSPARENT = 1;    

        [DllImport("gdi32.dll")]
        public extern static int SetBkMode(IntPtr hdc, int iBkMode);
    
        [DllImport("gdi32.dll")]
        public extern static int SetTextColor(IntPtr hdc, int crColor);
    
        [DllImport("gdi32.dll")]
        public extern static IntPtr SelectObject(IntPtr hdc, IntPtr hgdiobj);

        [DllImport("gdi32.dll", ExactSpelling=true, CharSet=CharSet.Auto)]
        public static extern bool DeleteObject(IntPtr hObject);

        [DllImport("user32.dll", ExactSpelling=true, CharSet=CharSet.Auto)]
        public static extern bool MessageBeep(int type);

        public class TextHelper
            {
            public static Size GetTextSize(Graphics graphics, string text, Font font)
                {
                IntPtr hdc = graphics.GetHdc();
                IntPtr fontHandle = font.ToHfont();
                IntPtr currentFontHandle = Win32.SelectObject(hdc, fontHandle);
            
                Win32.RECT rect = new Win32.RECT();
                rect.left = 0;
                rect.right = 0;
                rect.top = 0;
                rect.bottom = 0;
        
                Win32.DrawText(hdc, text, text.Length, ref rect, Win32.DT_SINGLELINE | Win32.DT_LEFT | Win32.DT_CALCRECT);
        
                Win32.SelectObject(hdc, currentFontHandle);
                Win32.DeleteObject(fontHandle);
                graphics.ReleaseHdc(hdc);
                
                return new Size(rect.right - rect.left, rect.bottom - rect.top);
                }
        
            public static void DrawText(Graphics graphics, string text, Point point, Font font, Color color)
                {
                Size size = GetTextSize(graphics, text, font);
        
                IntPtr hdc = graphics.GetHdc();
                IntPtr fontHandle = font.ToHfont();
                IntPtr currentFontHandle = Win32.SelectObject(hdc, fontHandle);
        
                int currentBkMode = Win32.SetBkMode(hdc, Win32.TRANSPARENT);
                int currentCrColor = Win32.SetTextColor(hdc, Color.FromArgb(0, color.R, color.G, color.B).ToArgb());
        
                Win32.RECT rc = new Win32.RECT();
                rc.left = point.X;
                rc.top = point.Y;
                rc.right = rc.left + size.Width;
                rc.bottom = rc.top + size.Height;
        
                Win32.DrawText(hdc, text, text.Length, ref rc, Win32.DT_SINGLELINE | Win32.DT_LEFT);            
        
                Win32.SetTextColor(hdc, currentCrColor);
                Win32.SetBkMode(hdc, currentBkMode);
    
                Win32.SelectObject(hdc, currentFontHandle);
                Win32.DeleteObject(fontHandle);
                graphics.ReleaseHdc(hdc);
                }
            }
    
        public class ImageHelper
            {
            static Version version = null;
    
            static ImageHelper()
                {
                Win32.DLLVERSIONINFO dvi = new Win32.DLLVERSIONINFO();
                dvi.cbSize = Marshal.SizeOf(typeof(Win32.DLLVERSIONINFO));
                Win32.DllGetVersion(ref dvi);
                version = new Version(dvi.dwMajorVersion, dvi.dwMinorVersion, dvi.dwBuildNumber, 0);
                }
    
            public static Version Version
                {
                get { return version; }
                }
    
            public static void DrawImage(Graphics graphics, Image image, Point point, bool disabled)
                {
                if (!disabled)
                    {
                    graphics.DrawImage(image, point);
                    return;                    
                    }
                    
                // Painting a disabled gray scale image is done using ILS_SATURATE on WinXP.
                // This code emulates that behaviour if comctl32 version 6 is not availble.
                if (version.Major < 6)
                    {
                    ImageAttributes attributes = new ImageAttributes();
                    Rectangle destination = new Rectangle(point, image.Size);
                    float[][] matrix = new float[5][];
                    matrix[0] = new float[] { 0.2222f, 0.2222f, 0.2222f, 0.0000f, 0.0000f };
                    matrix[1] = new float[] { 0.2222f, 0.2222f, 0.2222f, 0.0000f, 0.0000f };
                    matrix[2] = new float[] { 0.2222f, 0.2222f, 0.2222f, 0.0000f, 0.0000f };
                    matrix[3] = new float[] { 0.3333f, 0.3333f, 0.3333f, 0.7500f, 0.0000f };
                    matrix[4] = new float[] { 0.0000f, 0.0000f, 0.0000f, 0.0000f, 1.0000f };
                    attributes.SetColorMatrix(new ColorMatrix(matrix));
                    graphics.DrawImage(image, destination, 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, attributes);
                    }
                else
                    {
                    ImageList imageList = new ImageList();
                    imageList.ImageSize = image.Size;
                    imageList.ColorDepth = ColorDepth.Depth32Bit;        
                    imageList.Images.Add(image);
    
                    IntPtr hdc = graphics.GetHdc();
                    Win32.IMAGELISTDRAWPARAMS ildp = new Win32.IMAGELISTDRAWPARAMS();
                    ildp.cbSize = Marshal.SizeOf(typeof(Win32.IMAGELISTDRAWPARAMS));
                    ildp.himl = imageList.Handle;
                    ildp.i = 0; // image index
                    ildp.hdcDst = hdc;
                    ildp.x = point.X;
                    ildp.y = point.Y;
                    ildp.cx = 0;
                    ildp.cy = 0;
                    ildp.xBitmap = 0;
                    ildp.yBitmap = 0;
                    ildp.fStyle = Win32.ILD_TRANSPARENT;
                    ildp.fState = Win32.ILS_SATURATE;
                    ildp.Frame = -100;
                    Win32.ImageList_DrawIndirect(ref ildp);
                    graphics.ReleaseHdc(hdc);
                    return;
                    }
                }
            }
        }

========

重温WIN32 API ------ C++日志类的实现

http://blog.csdn.net/smstong/article/details/42083121


开发程序时,记录运行状态对于调试非常重要,从最简单好用的printf(),到VC++环境提供的TRACE宏,都是开发者的得力助手。其实打印记录程序运行状态的重要性还应该更加重要,不仅开发时,而且在部署完毕运行时,也要把运行状态通过日志文件展现出来,以便于


跟踪排查错误。看看现在大型的软件如Tomat,Oracle,IIS,无不提供了日志功能。可测量跟踪成为了软件健壮的重要标志。
1 基本思路
对于开发者来讲,不仅需要记录程序的状态,还要记录对应的源代码位置,记录的时间等。对于这些通用的记录项,就应该尽量自动的去完成,从而避免繁琐的日志代码,为此我开发了一个非常简单的C++日志类来完成这个工作。
 
为使用更加简单,全部日志功能通过一个宏定义导出,使用者只需 LOG(L"记录内容"); 即可,最终这个宏会自动把源文件位置,记录时间,连同日志一起作为一行写入日志文件。需要注意,字符编码全部要求是UNICODE编码。
2 代码实现

#pragma once  
/* 
                                 日志记录类 
功能描述: 
    根据当前时间自动生成日志文件名,自动记录日志到日志文件。 
 
    日志文件名格式(样例): 
    20141219211252255.log 
 
    日志内容格式(样例): 
    2014年12月19日11时52分55秒,源文件:e:\work\udptest\udptestdlg.cpp,第109行, 这里是要写的日志内容 
 
使用方式: 
    此类采用单例模式设计,为使用方便,定义了两个宏供用户调用。样例代码: 
    LOG(L"这里是要写的日志内容");  // 记录日志到文件 
    ENDLOG  // 程序退出之前调用,关闭日志文件 
 
 
*/  
class LogWriter  
{  
protected:  
    LogWriter();  
    ~LogWriter();  
private:  
    wchar_t fileName[1024];  
    FILE* fp;  
public:  
    void Log(wchar_t* log);  
public:  
    static LogWriter* GetLogWriter();  
    static void DeleteLogWriter();  
private:  
    static LogWriter* theOnlyLogWriter;  
};  
  
#define LOG(x) \  
    { \  
    wchar_t buffer[2048];\  
    SYSTEMTIME st;\  
    ::GetLocalTime(&st);\  
    swprintf_s(buffer, L"%04d年%02d月%02d日%02d时%02d分%02d秒,源文件:%s,第%d行, %s\n", \  
        st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond,\  
        TEXT(__FILE__),__LINE__,x);\  
    LogWriter::GetLogWriter()->Log(buffer);\  
    }  
  
#define ENDLOG \  
    LogWriter::DeleteLogWriter();  
 
#include "stdafx.h"  
#include "LogWriter.h"  
#include "share.h"  
LogWriter* LogWriter::theOnlyLogWriter = NULL;  
  
LogWriter::LogWriter()  
{  
    // determine the log file's name, yyyyMMddhhmmss.log  
    SYSTEMTIME st;  
    ::GetLocalTime(&st);  
    ::swprintf_s(this->fileName, L"%04d%02d%02d%02d%02d%02d.log", st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond);  
    fp = ::_wfsopen(this->fileName, L"w,ccs=UTF-8", _SH_DENYNO); // 以共享读写模式打开日志文件  
}  
  
// 线程安全的写入文件  
void LogWriter::Log(wchar_t* log)  
{  
    if (fp != NULL)  
    {  
        ::fwprintf(this->fp, L"%s", log);  
    }  
}  
LogWriter::~LogWriter()  
{  
    if (this->fp != NULL)  
        ::fclose(fp);  
}  
  
LogWriter* LogWriter::GetLogWriter()  
{  
    if (theOnlyLogWriter == NULL)  
    {  
        theOnlyLogWriter = new LogWriter();  
    }  
    return theOnlyLogWriter;  
}  
  
void LogWriter::DeleteLogWriter()  
{  
    if (theOnlyLogWriter != NULL)  
    {  
        delete theOnlyLogWriter;  
        theOnlyLogWriter = NULL;  
    }  
}

========

重温WIN32 API ------ 一个简单的UDP服务器类

http://blog.csdn.net/smstong/article/details/42082903


最近一个项目需要使用简单的UDP进行通信,为方便调用,使用C++类封装了一个简单的UDP服务器类。
1 基本思路
网络通信程序设计中最难的部分就是IO的处理,不同操作系统平台提供不同的IO处理机制,Windows平台有select模型、完成端口等,Linux平台则是poll和epoll。由于本项目要求简单,通信量也不大,所以没有采用这些与平台相关的IO模型,而是采用简单的专用线程来


负责侦听。当收到数据包时,自动调用用户指定的回调函数,算是设计模式中”订阅模式“的简单实现,也是来自于模仿C#中的event机制。
 
多线程程序必须要考虑同步的问题。主线程通过线程安全地设置一个变量来通知UDP侦听线程退出,为防止侦听线程中的recvfrom()一直阻塞而无法退出线程,主线程采用closesocket()来强制侦听线程的recvfrom()返回。(其他让recvfrom退出的方法包括发送专用udp数


据包)
 
另外类使用者需要注意的是,回调函数是在侦听线程中执行,所以要避免非UI线程直接更新UI的问题。回调函数如果涉及到窗口UI操作,需要处理数据后通过SendMessage()的方式通知UI线程,然后由UI线程来实际执行UI更新操作。
2 代码实现
就一个UDPServer类,头文件UDPServer.h,实现文件UDPServer.cpp

#pragma once  
  
#include <WinSock2.h>  
#include <Ws2tcpip.h>  
#include <iphlpapi.h>  
  
#pragma comment(lib, "IPHLPAPI.lib")  
#pragma comment(lib, "WS2_32")  
  
#include <vector>  
using namespace std;  
  
typedef void(*UDPRecvFun)(void* sender, BYTE*, int);   // 收到UDP数据包后的回调函数原型  
  
/* 
                            UDP服务器类 
功能描述: 
建立UDP侦听,建立一个专用线程负责接收UDP数据包。该类采用类似于C#的事件驱动设计模式。 
 
使用样例: 
    void AfterRecv(void* sender, BYTE* data, int len)  // 回调函数实现 
    { 
       ...... 
    } 
 
    UDPServer pServer = new UDPServer("127.0.0.1", 8888); 
    pServer.AddCallback(AfterRecv);    // 增加一个回调, 收到UDP包后会自动调用此函数 
 
    pServer->StartUDPServer(); // 开始侦听 
 
    pServer->StopUDPServer(); // 可选,因为析构函数会自动调用此方法 
 
    delete pServer; 
 
*/  
class UDPServer  
{  
public:  
    UDPServer(unsigned int ip, unsigned short port);  
    UDPServer(char* ip, unsigned short port);  
    ~UDPServer();  
  
protected:  
    static DWORD WINAPI UDPServerThreadFunc(void* state);  
    void StartUDPServer(unsigned int ip, unsigned short port);  
    void StartUDPServer(char* ip, unsigned short port);  
    void OnRecv(BYTE*, int);  
private:  
    unsigned long IP;  
    unsigned short port;  
    SOCKET sock; // socket  
    HANDLE tid;  // 侦听线程ID  
    CRITICAL_SECTION cs; // 线程同步用  
    int isEnd; // 是否终止侦听  
    vector<UDPRecvFun> listOnRecv;  // 收到UDP包后的回调函数列表  
public:  
    SOCKET GetSocket(){ return this->sock; }  
protected:  
    int GetIsEnd();  
    void SetIsEnd(int n);  
public:  
    void StartUDPServer();  
    void StopUDPServer();  
    void AddCallback(UDPRecvFun cb); // 增加一个回调函数  
};  
 

#include "stdafx.h"  
#include "UDPServer.h"  
#include "LogWriter.h"  
  
UDPServer::UDPServer(unsigned int ip, unsigned short port)  
{  
    this->sock = NULL;  
    this->tid = NULL;  
    this->listOnRecv.clear();  
    this->IP = ip;  
    this->port = port;  
    ::InitializeCriticalSection(&this->cs);  
    isEnd = 0;  
}  
  
UDPServer::UDPServer(char* ip, unsigned short port)  
{  
    this->sock = NULL;  
    this->tid = NULL;  
    this->listOnRecv.clear();  
    this->IP = ::inet_addr(ip);  
    this->port = port;  
    ::InitializeCriticalSection(&this->cs);  
    isEnd = 0;  
}  
UDPServer::~UDPServer()  
{  
    if (this->tid != NULL)  
    {  
        StopUDPServer();  
    }  
  
    ::DeleteCriticalSection(&this->cs);  
}  
  
/* 
功能:线程安全地设置isEnd 
*/  
void UDPServer::SetIsEnd(int n)  
{  
    ::EnterCriticalSection(&this->cs);  
    this->isEnd = n;  
    ::LeaveCriticalSection(&this->cs);  
}  
  
/* 
功能: 线程安全地读取isEnd 
*/  
int UDPServer::GetIsEnd()  
{  
    ::EnterCriticalSection(&this->cs);  
    int r = this->isEnd;  
    ::LeaveCriticalSection(&this->cs);  
    return r;  
}  
/* 
功能:停止UDP服务器(线程) 
*/  
void UDPServer::StopUDPServer()  
{  
    if (this->tid != NULL)  
    {  
        this->SetIsEnd(1);         // 设置停止标记  
        ::closesocket(this->sock);// 唤醒recvfrom() //::shutdown(this->sock, SD_BOTH); 不好用  
        this->sock = NULL;  
  
        ::WaitForSingleObject(this->tid, INFINITE);// 等待UDP专用线程结束  
        this->tid = NULL;  
    }  
}  
  
/* 
功能:调用回调列表里的所有函数 
*/  
void UDPServer::OnRecv(BYTE* data, int len)  
{  
    vector<UDPRecvFun>::iterator it;  
    for (it = this->listOnRecv.begin(); it != this->listOnRecv.end(); it++)  
    {  
        if (*it != NULL)  
        {  
            (*it)(this, data, len);  
        }  
    }  
}  
  
/* 
功能:启动UDP侦听服务器 
参数:ip-侦听IP字符串; port-侦听端口 
*/  
void UDPServer::StartUDPServer(char* ip, unsigned short port)  
{  
    unsigned long nIP = ::inet_addr(ip);  
    if (nIP == INADDR_NONE)  
    {  
        LOG(L"IP 地址%s 错误");  
        return;  
    }  
    this->StartUDPServer(nIP, port);  
}  
  
/* 
线程函数传参结构,用于安全地向子线程传参 
*/  
class UDPThreadState  
{  
public:  
    UDPServer* obj;  
    SOCKET scok;  
};  
  
/* 
功能:开启UDP侦听线程, 本函数不阻塞 
参数:ip - 侦听IP,port-侦听端口 
*/  
void UDPServer::StartUDPServer(unsigned int ip, unsigned short port)  
{  
    if (this->sock != NULL) return;  
  
    this->sock = ::socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);  
    if (sock == INVALID_SOCKET)  
    {  
        this->sock = NULL;  
        LOG(L"UDP服务器创建socket失败");  
        return;  
    }  
    sockaddr_in sin;  
    sin.sin_family = AF_INET;  
    sin.sin_port = htons(port);  
    sin.sin_addr.S_un.S_addr = ip;  
  
    if (::bind(sock, (sockaddr*)&sin, sizeof(sin)) == SOCKET_ERROR)  
    {  
        LOG(L"bind() failed");  
        return;  
    }  
  
    wchar_t log[1024];  
    swprintf_s(log, L"UDP服务器绑定到了 %S:%d",  
        ::inet_ntoa(sin.sin_addr), ::ntohs(sin.sin_port)); // 注意%S与%s  
    LOG(log);  
  
    UDPThreadState* state = new UDPThreadState();  
    state->obj = this;  
    state->scok = sock;  
    this->tid = ::CreateThread(NULL, 0, UDPServerThreadFunc, (void*)state, NULL, NULL);  
    if (tid == NULL)  
    {  
        delete state;  
    }  
}  
/* 
功能:UDP 侦听线程函数,静态函数 
参数:符合ThreadProc规范要求 
*/  
DWORD UDPServer::UDPServerThreadFunc(void* state)  
{  
    // 解析线程函数参数  
    UDPThreadState* pstate = (UDPThreadState*)state;  
    UDPServer* obj = pstate->obj;  
    SOCKET sockServer = pstate->scok;  
    delete pstate; pstate = NULL;  
  
    wchar_t log[100];  
    swprintf_s(log, L"UDP侦听线程 %d 已经启动", ::GetCurrentThreadId());  
    LOG(log);  
  
    char buff[1024];  
    sockaddr_in remoteAddr;  
    int nLen = sizeof(remoteAddr);  
    while (1)  
    {  
        if (1 == obj->GetIsEnd())  
        {  
            break;  
        }  
        int n = ::recvfrom(sockServer, buff, 1024, 0, (sockaddr*)&remoteAddr, &nLen);  
        if (n == SOCKET_ERROR)  
        {  
            wchar_t log[128];  
            swprintf_s(log, L"recvfrom返回错误号:%d", ::WSAGetLastError());  
            LOG(log);  
        }  
        else if (n == 0)  
        {  
            LOG(L"socket关闭,recvfrom() 退出");  
        }  
        else  
        {  
            wchar_t log[128];  
            swprintf_s(log, L"接收到UDP包, 大小%d字节,来自%S:%d",  
                n, ::inet_ntoa(remoteAddr.sin_addr), ::ntohs(remoteAddr.sin_port)); // 注意%S与%s  
            LOG(log);  
            obj->OnRecv((BYTE*)buff, n);  
        }  
    }  
  
    swprintf_s(log, L"UDP侦听线程 %d 退出", ::GetCurrentThreadId());  
    LOG(log);  
    return 0;  
}  
/* 
功能:启动侦听 
*/  
void UDPServer::StartUDPServer()  
{  
    this->StartUDPServer(this->IP, this->port);  
}  
  
/* 
功能:向回调函数链表中增加一个回调函数 
参数:cb-用户定义的回调函数名 
*/  
void UDPServer::AddCallback(UDPRecvFun cb)  
{  
    this->listOnRecv.push_back(cb);  
}

测试代码:

Radar::Radar()  
{  
    // 建立服务器1  
    this->pUDPServer = new UDPServer(”172.16.35.144", 8888);  
    this->pUDPServer->AddCallback(Radar::AfterRecvUDP);  
  
    // 建立服务器2  
    pUDPServer2 = new UDPServer("172.16.35.144", 9999);  
    pUDPServer2->AddCallback(Radar::AfterRecvUDP);  
}  

// 回调函数  
void Radar::AfterRecvUDP(void* sender, BYTE* data, int len)  
{  
    data[len] = 0;  
    ::MessageBoxA(::AfxGetApp()->GetMainWnd()->m_hWnd, (char*)data, "C", MB_OK);  
} 

========

重温 Win32 API ----- 截屏指定窗口并打印

http://blog.csdn.net/smstong/article/details/42082039


朋友说在一个VC++6.0开发的项目中要加入打印窗口的功能,让帮忙写个代码供其调用。这么老的IDE当然不想碰了,而且也不喜欢MFC笨拙不清晰的封装,所以决定采用纯Win32 API,然后用C++类简单封装一下。
1 基本思路
窗口DC和打印机DC是两类不兼容的DC,所以它们之间传送位图只能通过DIB。首先,通过BitBlt()把要打印窗口的客户区拷贝到DDB内存位图中,然后通过GetDIBits()把DDB转换为DIB,最后通过StretchDIBits()向打印机DC输出。
2 代码实现
头文件 WinowPrinter.h

#pragma once  
  
/******************************************************************************** 
                         WindowPrinter 打印窗口类 
功能描述: 
提供截屏窗口并通过默认打印机,自动进行居中缩放打印 
 
使用说明: 
样例代码如下。  
    HWND hwnd = this->GetSafeWnd(); 
    WindowPrinter::PrintWindowClientArea(hwnd); 
********************************************************************************/  
class WindowPrinter  
{  
public:  
    WindowPrinter();  
    ~WindowPrinter();  
public:  
    /* 
    功能:获取当前默认打印机的DC 
    返回:成功返回打印机的DC,失败返回NULL 
    */  
    static HDC GetPrinterDC();  
  
    /* 
    功能:打印窗口客户区内容到打印机,自动缩放居中打印 
    参数: hWnd-被打印窗口的句柄 
    */  
    static void PrintWindowClientArea(HWND hwnd);  
};

实现文件 WindowPrinter.cpp

#include "stdafx.h"  
#include "WindowPrinter.h"  
#include <Winspool.h>  
 
WindowPrinter::WindowPrinter()  
{  
}  
  
WindowPrinter::~WindowPrinter()  
{  
}  
  
/* 
功能:获取当前默认打印机的DC 
返回:成功返回打印机的DC,失败返回NULL 
*/  
HDC WindowPrinter::GetPrinterDC()  
{  
    DWORD dwNeeded, dwReturned;  
    HDC hdc;  
    ::EnumPrinters(PRINTER_ENUM_LOCAL, NULL, 4, NULL, 0, &dwNeeded, &dwReturned);  
    PRINTER_INFO_4* pinfo4 = (PRINTER_INFO_4*)malloc(dwNeeded);  
    ::EnumPrinters(PRINTER_ENUM_LOCAL, NULL, 4, (BYTE*)pinfo4, dwNeeded, &dwNeeded, &dwReturned);  
    hdc = ::CreateDC(NULL, pinfo4->pPrinterName, NULL, NULL);  
    free(pinfo4);  
    return hdc;  
}  
/* 
功能:打印窗口客户区内容到打印机,自动缩放居中打印 
参数: hWnd-被打印窗口的句柄 
*/  
void WindowPrinter::PrintWindowClientArea(HWND hWnd)  
{  
    if (hWnd == NULL) return;  
  
    RECT rectClient;  
    ::GetClientRect(hWnd, &rectClient);  
    int width = rectClient.right - rectClient.left;  
    int height = rectClient.bottom - rectClient.top;  
  
    // 通过内存DC复制客户区到DDB位图  
    HDC hdcWnd = ::GetDC(hWnd);  
    HBITMAP hbmWnd = ::CreateCompatibleBitmap(hdcWnd, width, height);  
    HDC hdcMem = ::CreateCompatibleDC(hdcWnd);  
    ::SelectObject(hdcMem, hbmWnd);  
    ::BitBlt(hdcMem, 0, 0, width, height, hdcWnd, 0, 0, SRCCOPY);  
  
    // 把窗口DDB转为DIB  
    BITMAP bmpWnd;  
    ::GetObject(hbmWnd, sizeof(BITMAP), &bmpWnd);  
    BITMAPINFOHEADER bi; // 信息头  
    bi.biSize = sizeof(BITMAPINFOHEADER);  
    bi.biWidth = bmpWnd.bmWidth;  
    bi.biHeight = bmpWnd.bmHeight;  
    bi.biPlanes = 1;  
    bi.biBitCount = 32; // 按照每个像素用32bits表示转换  
    bi.biCompression = BI_RGB;  
    bi.biSizeImage = 0;  
    bi.biXPelsPerMeter = 0;  
    bi.biYPelsPerMeter = 0;  
    bi.biClrUsed = 0;  
    bi.biClrImportant = 0;  
  
    DWORD dwBmpSize = ((bmpWnd.bmWidth * bi.biBitCount + 31) / 32) * 4 * bmpWnd.bmHeight; // 每一行像素位32对齐  
    char *lpbitmap = (char*)malloc(dwBmpSize); // 像素位指针  
    ::GetDIBits(hdcMem, hbmWnd, 0, (UINT)bmpWnd.bmHeight,  
        lpbitmap,  
        (BITMAPINFO*)&bi,  
        DIB_RGB_COLORS);  
  
    ::DeleteDC(hdcMem);  
    ::DeleteObject(hbmWnd);  
    ::ReleaseDC(hWnd, hdcWnd);  
  
    // 存为文件(可选)  
    BITMAPFILEHEADER bmfHeader; // 文件头  
    DWORD dwSizeofDIB = dwBmpSize + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);  
    bmfHeader.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + (DWORD)sizeof(BITMAPINFOHEADER);  
    bmfHeader.bfSize = dwSizeofDIB;  
    bmfHeader.bfType = 0x4D42;  
  
    FILE* fp = NULL;  
    ::_wfopen_s(&fp, L"capture.bmp", L"w");  
    ::fwrite(&bmfHeader, sizeof(BITMAPFILEHEADER), 1, fp); // 写入文件头  
    ::fwrite(&bi, sizeof(BITMAPINFOHEADER), 1, fp);        // 写入信息头  
    ::fwrite(lpbitmap, dwBmpSize, 1, fp);                  // 写入像素位  
    ::fclose(fp);  
    fp = NULL;  
  
    // StretchDIBits()缩放打印DIB  
    HDC hdcPrinter = WindowPrinter::GetPrinterDC();  
    if (hdcPrinter == NULL)  
        return;  
  
    int pageWidth = ::GetDeviceCaps(hdcPrinter, HORZRES);  
    int pageHeight = ::GetDeviceCaps(hdcPrinter, VERTRES);  
  
    float scaleX = (float)pageWidth / (float)bmpWnd.bmWidth;  
    float scaleY = (float)pageHeight / (float)bmpWnd.bmHeight;  
    float scale = scaleX < scaleY ? scaleX : scaleY;  
  
    int xDst, yDst, cxDst, cyDst;  
    cxDst = (int)((float)bmpWnd.bmWidth * scale);  
    cyDst = (int)((float)bmpWnd.bmHeight * scale);  
    xDst = (int)((pageWidth - cxDst) / 2);  
    yDst = (int)((pageHeight - cyDst) / 2);  
  
    static DOCINFO di = { sizeof(DOCINFO), L"PRINTJOBNAME" };  
    if (::StartDoc(hdcPrinter, &di) > 0)  
    {  
        if (::StartPage(hdcPrinter) > 0)  
        {  
            ::StretchDIBits(hdcPrinter,  
                xDst, yDst, cxDst, cyDst,  
                0, 0, bmpWnd.bmWidth, bmpWnd.bmHeight,  
                lpbitmap,  
                (BITMAPINFO*)&bi,  
                DIB_RGB_COLORS,  
                SRCCOPY);  
            ::EndPage(hdcPrinter);  
        }  
        ::EndDoc(hdcPrinter);  
    }  
    ::DeleteDC(hdcPrinter);  
    ::free(lpbitmap);  
}

========

C++ Win32 API Hook类

http://www.newxing.com/Tech/Program/Cpp/700.html


HookApi.h

#include <windows.h>
#ifndef _HOOKAPI_H
#define _HOOKAPI_H

class CHOOKAPI {
public:
    LPVOID    pOldFunEntry, pNewFunEntry ;    // 初始函数地址、HOOK后的函数地址
    BYTE    bOldByte[5], bNewByte[5] ;        // 原始字节、目标字节

public:
    CHOOKAPI () {}
    ~CHOOKAPI() {}
    // 实现HOOK API
    void Hook ( PSTR szModuleName, PSTR szFunName, FARPROC pFun )
    {   
        HMODULE    hMod = ::GetModuleHandleA ( szModuleName ) ;
        if ( hMod != NULL )
        {
            pNewFunEntry    = (LPVOID)pFun ;
            pOldFunEntry    = (LPVOID)GetProcAddress ( hMod, szFunName ) ;
            bNewByte[0]        = 0xE9 ;
            *((PDWORD)(&(bNewByte[1])))    = (DWORD)pNewFunEntry - (DWORD)pOldFunEntry - 5 ;

            DWORD   dwProtect, dwWriteByte, dwReadByte ;
            VirtualProtect ( (LPVOID)pOldFunEntry, 5, PAGE_READWRITE, &dwProtect );
            ReadProcessMemory    ( GetCurrentProcess(), (LPVOID)pOldFunEntry, bOldByte, 5, &dwReadByte ) ;       
            WriteProcessMemory    ( GetCurrentProcess(), (LPVOID)pOldFunEntry, bNewByte, 5, &dwWriteByte ) ;
            VirtualProtect ( (LPVOID)pOldFunEntry, 5, dwProtect, NULL ) ;
        }
    }
    // 重新HOOK
    void ReHook ()
    {
        DWORD    dwProtect, dwWriteByte ;
        VirtualProtect ( pOldFunEntry, 5, PAGE_READWRITE, &dwProtect );
        WriteProcessMemory ( GetCurrentProcess(), pOldFunEntry, bNewByte, 5, &dwWriteByte ) ;
        VirtualProtect ( pOldFunEntry, 5, dwProtect, NULL ) ;
    }
    // 撤消HOOK
    void UnHook ()
    {
        DWORD    dwProtect, dwWriteByte ;
        VirtualProtect ( pOldFunEntry, 5, PAGE_READWRITE, &dwProtect );
        WriteProcessMemory ( GetCurrentProcess(), pOldFunEntry, bOldByte, 5, &dwWriteByte ) ;
        VirtualProtect ( pOldFunEntry, 5, dwProtect, NULL ) ;
    }
} ;

#endif

调用测试:

#include "stdafx.h"
#include "HookApi.h"
CHOOKAPI    HookItem ;

// 定义MessageBoxA函数原型
typedef int (WINAPI* PFNMessageBoxA)( HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType ) ;

// 自定义的MessageBoxA函数
// 实现对原始MessageBoxA的输入、输出参数的监控,甚至是取消调用
int WINAPI New_MessageBoxA( HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType )
{
    // 撤消HOOK
    HookItem.UnHook () ;
   
    // 此处可以观察/修改调用参数,甚至可以取消调用直接返回。
    // ……
   
    // 取得原函数地址
    PFNMessageBoxA pfnMessageBoxA = (PFNMessageBoxA)HookItem.pOldFunEntry ;
   
    // 调用原函数,修改输入参数
    int ret = pfnMessageBoxA ( hWnd, "这是HOOK函数过程的消息框", "[测试]", uType ) ;
   
    // 此处可以查看/修改调用原函数的返回值
    // ……
   
    // 重新HOOK
    HookItem.ReHook () ;
   
    return ret ;
}

int main(int argc, char* argv[])
{
    // 原始API
    MessageBoxA ( 0, "正常消息框", "测试", 0 ) ;
   
    // HOOK API
    HookItem.Hook ( "USER32.dll", "MessageBoxA", (FARPROC)New_MessageBoxA ) ;
   
    // 调用API,测试
    MessageBoxA ( 0, "正常消息框", "测试", 0 ) ;

    // 撤消HOOK
    HookItem.UnHook () ;

    printf("Hello World!\n");
    return 0;
}

========

win32api做界面

http://twopointfive.blog.163.com/blog/static/9005854320150402627767/
    在windows平台上做界面,很多人使用第三方库,c#或mfc。都可以和d3d或opengl结合,制作像场景编辑器一类既需要3d又需要2d的工具。然而都不是很方便,所以一直研究怎样直接使用win32api来做界面。有兴趣的可以继续完善。

#ifndef __WAGuiCtrl_H__
#define __WAGuiCtrl_H__

#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0500
#endif
#ifndef WINVER
#define WINVER 0x0500
#endif

#include <Windows.h>
#include <winuser.h>
#include <commctrl.h>
#include <string>
#include <map>
#include <vector>

class WATool  
{
public:
	static bool SetTransparent(HWND hWnd, int nOpactiy=220, BOOL bTransparent=true);
	//	cTransparentColor :	Color base for the "transparent" pixels (default is black)
	//	cTolerance :		Color tolerance for the "transparent" pixels.
	static HRGN BitmapToRegion (HBITMAP hBmp, COLORREF cTransparentColor = 0, COLORREF cTolerance = 0x101010);

};

enum CtrlType
{
	CT_NULL = 0,
	CT_STATIC,
	CT_BURRON,
	CT_EDIT,
	CT_LISTBOX,
	CT_LISTCTRL,
	CT_TREE,
	CT_DIALOG
};

class WAGuiCtrl
{
public:
	WAGuiCtrl():m_mousePressed(false){}
	virtual ~WAGuiCtrl() = 0{};
	HWND m_hwndMain;
	virtual bool Create(HWND hwndParent, LPSTR szWindowName,LPSTR idName = ""){return true;};
	//HWND operator()(){return m_hwndMain;};
	//HWND operator HWND(){return m_hwndMain;};
    bool operator==(HWND hwnd){return m_hwndMain == hwnd;}

	void SetRect(int x,int y,int w,int h)
	{
	    //SetWindowPos(m_hWnd,HWND_TOPMOST,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE);
		//SetWindowPos,MoveWindow(x,y,height,width) xy是相对于父窗口 原点在左上角
		SetWindowPos(m_hwndMain, HWND_TOP,x, y,w, h,SWP_SHOWWINDOW);
	}

	void ModifyWndStyle(WORD style,WORD remove,WORD add)
	{			
		//^  按位异或 对应位不相同时为1。
        //~ 所有位都反转。
		long s = GetWindowLong(m_hwndMain, style);
		s &= (~remove);
		s |= add;
		SetWindowLong(m_hwndMain, style, s);
	}

	std::string m_idName;


	POINT m_lastMouseDownPt;
	bool  m_mousePressed;

	//delegte command  dialog proc call then call back
};

class WAGuiButtonCtrl:public WAGuiCtrl
{
public:
	virtual bool Create(HWND hwndParent, LPSTR szWindowName,LPSTR idName = "");
	//HWND CreateButton(HWND hwndParent, LPSTR szWindowName,LPSTR idName = "",DWORD types = BS_PUSHBUTTON);

};

class WAGuiStaticCtrl:public WAGuiCtrl
{
public:
	virtual bool Create(HWND hwndParent, LPSTR szWindowName,LPSTR idName = "");
};

class WAGuiComboBoxCtrl:public WAGuiCtrl
{
public:
	virtual bool Create(HWND hwndParent, LPSTR szWindowName,LPSTR idName = "");
	int   GetComboBoxSelect(HWND hwnd);   
	void  InsertComboBoxString(HWND hwnd,int row,LPSTR name);
	void  SetComboBoxSelect(HWND hwnd,int row);
};

class WAGuiEditCtrl:public WAGuiCtrl
{
public:
	virtual bool Create(HWND hwndParent, LPSTR szWindowName,LPSTR idName = "");
	void  SetText(LPSTR szTextToShow);
	int   GetEditInt(HWND hwnd);				
	float GetEditFloat(HWND hwnd);				
	LPSTR GetEditString(HWND hwnd);	
	void  SetEditInt(HWND hwnd,int value);		
	void  SetEditFloat(HWND hwnd,float value);	
	void  SetEditString(HWND hwnd,LPSTR text);
};

class WAGuiListBoxCtrl:public WAGuiCtrl
{
public:
	virtual bool Create(HWND hwndParent, LPSTR szWindowName,LPSTR idName = "");
	int   GetSelectLine(); 
	int   GetCount(); 
	int   GetSelCount();
	int   GetSelItems();
	void  InsertItem(int row,LPSTR name);
	void  RemoveItem(int row);

	void  GetText(LPSTR*buffer,int row);
};

class WAGuiListViewCtrl:public WAGuiCtrl
{
public:
	virtual bool Create(HWND hwndParent, LPSTR szWindowName,LPSTR idName = "");
	BOOL AddListViewItems(HWND hwndListView);
	BOOL InitListViewColumns(HWND hWndListView);
	BOOL GetImageList(HIMAGELIST * pHiml);
	BOOL InitListViewImageLists(HWND hWndListView);
};

class WAGuiTreeCtrl:public WAGuiCtrl
{
public:
	virtual bool Create(HWND hwndParent, LPSTR szWindowName,LPSTR idName = "");
	BOOL         InitTreeViewItems(HWND hwndTV);
	HTREEITEM    AddItemToTree(HWND hwndTV, LPSTR lpszItem, HTREEITEM hParent, BOOL bFolder);
	BOOL         InitTreeViewImageLists(HWND hwndTV);

};

#include <shlobj.h>
#include <exdisp.h>
#include <mshtmlc.h>
#import  "PROGID:ShockwaveFlash.ShockwaveFlash" no_namespace raw_interfaces_only
//#import   "c:\winnt\system32\macromed\flash\swflash.ocx " 
//using   namespace   ShockwaveFlashObjects;
//import flash.ocx 会自动导出flash.tlh到temp文件夹 其中包含一些接口定义如IShockwaveFlash以便用户查询使用
//可以导入一个本地路径的 .ocx 然后运行时注册(先判断是否已经注册 读注册表 win7和xp不同?) 退出时反注册
typedef HRESULT (WINAPI *LPAtlAxWinInit)   ();
typedef HRESULT (WINAPI *LPAtlAxGetControl)(HWND hwnd, IUnknown** unk);
typedef HRESULT (WINAPI *LPAtlAxAttachControl)(IDispatch*,HWND hwnd, IUnknown** unk);
class WAGuiFlashCtrl;
class FlashCmdRecv:public _IShockwaveFlashEvents
{
public:
	WAGuiFlashCtrl* m_ctrl;
	//DShockwaveFlashEvents
    HRESULT STDMETHODCALLTYPE OnReadyStateChange (
        long newState );
    HRESULT STDMETHODCALLTYPE OnProgress (
        long percentDone );
    HRESULT STDMETHODCALLTYPE FSCommand (
        BSTR command,
        BSTR args );
	HRESULT STDMETHODCALLTYPE FlashCall(
		BSTR request);

	//IDispatch proto
    virtual HRESULT STDMETHODCALLTYPE GetTypeInfoCount( 
        /* [out] */ UINT __RPC_FAR *pctinfo);
    virtual HRESULT STDMETHODCALLTYPE GetTypeInfo( 
        /* [in] */ UINT iTInfo,
        /* [in] */ LCID lcid,
        /* [out] */ ITypeInfo __RPC_FAR *__RPC_FAR *ppTInfo);
    virtual HRESULT STDMETHODCALLTYPE GetIDsOfNames( 
        /* [in] */ REFIID riid,
        /* [size_is][in] */ LPOLESTR __RPC_FAR *rgszNames,
        /* [in] */ UINT cNames,
        /* [in] */ LCID lcid,
        /* [size_is][out] */ DISPID __RPC_FAR *rgDispId);
	//这里可以收到FSCommand消息回调
    virtual /* [local] */ HRESULT STDMETHODCALLTYPE Invoke( 
        /* [in] */ DISPID dispIdMember,
        /* [in] */ REFIID riid,
        /* [in] */ LCID lcid,
        /* [in] */ WORD wFlags,
        /* [out][in] */ DISPPARAMS __RPC_FAR *pDispParams,
        /* [out] */ VARIANT __RPC_FAR *pVarResult,
        /* [out] */ EXCEPINFO __RPC_FAR *pExcepInfo,
        /* [out] */ UINT __RPC_FAR *puArgErr);

	//IUnknown proto
	int m_iRef;
	HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void ** ppvObject);
	ULONG STDMETHODCALLTYPE AddRef();
	ULONG STDMETHODCALLTYPE Release();
};

class WAGuiFlashCtrl:public WAGuiCtrl
{
public:
	WAGuiFlashCtrl()
	{
		flash=0; 
		view =0;
		m_dwCookie = 0;
		pCPC = NULL;  
		m_pCP = NULL;
		testThis = this;
	}
	static WAGuiFlashCtrl* testThis;
	virtual bool Create(HWND hwndParent, LPSTR szWindowName,LPSTR idName = "");
    FlashCmdRecv m_cmdRecv;
	HRESULT STDMETHODCALLTYPE FSCommand (BSTR command,BSTR args );

	IShockwaveFlash*           flash; 
	IViewObjectEx*             view;
	DWORD                      m_dwCookie;
	LPCONNECTIONPOINTCONTAINER pCPC;  
	LPCONNECTIONPOINT          m_pCP; 

};

class WAGuiHtmlCtrl:public WAGuiCtrl
{
public:
	virtual bool Create(HWND hwndParent, LPSTR szWindowName,LPSTR idName = "");

};

class WAGuiDialog:public WAGuiCtrl
{
public:
	WAGuiDialog(){}
	virtual ~WAGuiDialog(){};
	virtual bool Create(HWND hwndParent, LPSTR szWindowName,LPSTR idName = "");
    static  bool Init();
	virtual LRESULT WinProc(UINT uMsg, WPARAM wParam,LPARAM lParam);
	virtual bool OnChildWindowsNotify(PVOID pParam){return true;};

	void Invalidate();

protected:
	HWND CreateButton(HWND hwndParent, LPSTR szWindowName,LPSTR idName = "",DWORD types = BS_PUSHBUTTON);
	
	VOID APIENTRY DisplayContextMenu(HWND hwnd, POINT pt);

	void  InsertListCtrlColumn(HWND hwnd,int row,LPSTR name);
	bool  GetCheckBool(HWND hwnd);				
	void  SetCheckBool(HWND hwnd,bool value);	

	//弹出“浏览文件夹”对话框
	DWORD Browse(HWND hwnd);

	/* VOID DoPaint(HWND hWnd, DWORD dwMode)
	* 功能 将位图(全局变量ghBitmap)显示在界面上
	* DWORD dwMode,模式,是否拉申
	*/
	VOID DoPaint(HWND hWnd, HBITMAP bitmap,DWORD dwMode);

	HWND m_hwndParent;
	static WNDCLASSEX wcx;


	//void Free();
    bool LoadFromFile(char* _filename);
	void SaveToFile(char* _filename);
	//virtual void SetVisible(BOOL _visible);

	virtual void MapCtrl(){}
	    
	template<typename T>
	void MAPCTRL(std::string idName,T& ctrl)
    {
		if(m_strCtrls[idName] == NULL) ;//log error
    	ctrl = dynamic_cast<T> (m_strCtrls[idName]);
    }

private:
	typedef std::vector<WAGuiCtrl*> CtrlVec;
	CtrlVec m_ctrls;

protected:
	struct StringPtrLess:
		public std::binary_function<std::string,std::string, bool> 
	{
		bool operator()(const std::string& ps1, const std::string& ps2) const
		{
			return strcmp(ps1.c_str(),ps2.c_str())<0;
		}
	};	
	typedef std::map<std::string,WAGuiCtrl*,StringPtrLess> StrCtrlMap;
    StrCtrlMap m_strCtrls;
};

#endif

#ifndef __WAGUI_H__
#define __WAGUI_H__
#include "WAGuiCtrl.h"
#include "WAGuiTopAnim.h"
enum DialogType
{
	DT_NULL = 0,
	DT_TEST,
	DT_NUM
};

class WAGuiTestDialog:public WAGuiDialog
{
public:
	WAGuiTestDialog()
		:m_hwndTreeView(NULL){}
	virtual bool Create(HWND hwndParent, LPSTR szWindowName,LPSTR idName = "");
	virtual LRESULT WinProc(UINT uMsg, WPARAM wParam,LPARAM lParam);
    virtual bool OnChildWindowsNotify(PVOID pParam);
    bool OnRclickTree(NMHDR* pNMHDR);
	virtual void MapCtrl();

private:
	WAGuiTreeCtrl*     m_hwndTreeView ;
	WAGuiListViewCtrl* m_hwndListView ;
	WAGuiListBoxCtrl*  m_hwndListBox ;
	WAGuiEditCtrl*     m_hwndEdit;
	WAGuiFlashCtrl*    m_hwndFlash;
	HWND m_hwndButton;

};

class WAGuiMgr
{
public:
	WAGuiMgr();
	~WAGuiMgr()
	{
		if(m_hBitmap)
		    DeleteObject(m_hBitmap);
	}
	void Init(HWND hwnd,HINSTANCE inst = NULL);	
    //d3d flip 后刷新使不闪
	void Invalidate();

    HBITMAP m_hBitmap;
	HBITMAP TestScreenCapture();


	/* 功能 截取指定区域的屏幕,并保存为文件
	*  参数	LPSTR filename 保存位图文件的文件路径,如果为NULL,则不保存
	*		WORD BitCount Bit深度,用于表示一个像素点所使用的数据长度
	*		LPRECT lpRect 所需截取的屏幕区域,如果为NULL,则获取全屏幕
	*/
	HBITMAP ScreenCapture(LPSTR filename ,WORD BitCount,LPRECT lpRect);

	/*
	* 功能	遍历目录及所有子目录,打印路径
	*/
	DWORD ListAllFileInDrectory(LPSTR szPath);


	//HCURSOR hnewCur;
	//hnewCur=LoadCursor(hInstance,MAKEINTRESOURCE(NEWCURSOR);
	//hnewCur=LoadCursorFromFile("normal.ani");
	//SetSystemCursor(hnewCur,OCR_NORMAL);
	//使用用户定义鼠标替换系统默认鼠标,当用户再次使用LoadCursor(NULL,IDC_ARROW);加载标准鼠标时获得的将是用户加载的而非系统预定义的鼠标 
	

//private:
	HWND m_hwndParent;
    HINSTANCE m_hinst;
	WAGuiDialog* m_dialogs[DT_NUM];

	WAGuiTopAnim m_topAnim;

};

extern WAGuiMgr G_GuiMgr;


#endif

#include "WAGuiCtrl.h"
#include "resource.h"
#include <shlobj.h>
#include <string>
#include <map>
#pragma comment(lib,"comctl32.lib")
#include <stdio.h>
#pragma comment (lib, "User32.lib")
#include <assert.h>

#include "BasicExcel.h"
using namespace YExcel;
	
bool WATool::SetTransparent(HWND hWnd, int nOpacity, BOOL bTransparent)
{
    if (bTransparent)
	{
		assert(nOpacity >= 0 && nOpacity <= 255);
		assert(hWnd && ::IsWindow(hWnd));
		long l = GetWindowLong(hWnd, GWL_EXSTYLE);
		l |= WS_EX_LAYERED;
		SetWindowLong(hWnd, GWL_EXSTYLE, l);
		SetLayeredWindowAttributes(hWnd, 0, nOpacity, LWA_ALPHA);		
	}
	else
	{
		long l = GetWindowLong(hWnd, GWL_EXSTYLE);
		l ^= WS_EX_LAYERED;
		SetWindowLong(hWnd, GWL_EXSTYLE, l);
		RECT r;
		::GetWindowRect(hWnd, &r);
		::InvalidateRect(hWnd, &r, true);
	}
	return true;
}

bool WAGuiStaticCtrl::Create(HWND hwndParent, LPSTR szWindowName,LPSTR idName)
{
	m_hwndMain = CreateWindow(
		TEXT("STATIC"), 
		NULL, // 没有标题
		// 窗口样式
		WS_CHILD | WS_VISIBLE | WS_BORDER, 
		// 位置和大小
		CW_USEDEFAULT ,
		CW_USEDEFAULT, 
		CW_USEDEFAULT, 
		CW_USEDEFAULT, 
		hwndParent, // 父窗口
		(HMENU) NULL, // 无菜单
		GetModuleHandle(NULL), // 实例句柄
		(LPVOID) NULL); 

	if (!m_hwndMain)
	{
		return false;
	}
	SetWindowText(m_hwndMain,szWindowName);
	ShowWindow(m_hwndMain, SW_SHOW);
	UpdateWindow(m_hwndMain);
	return true;
}
//
//bool WAGuiButtonExCtrl::Create(HWND hwndParent, LPSTR szWindowName,LPSTR idName)
//{
//	m_hwndMain = CreateWindow(
//		TEXT("BUTTON"), 
//		NULL, // 没有标题
//		// 窗口样式
//		WS_CHILD | WS_VISIBLE | WS_BORDER, 
//		// 位置和大小
//		CW_USEDEFAULT ,
//		CW_USEDEFAULT, 
//		CW_USEDEFAULT, 
//		CW_USEDEFAULT, 
//		hwndParent, // 父窗口
//		(HMENU) NULL, // 无菜单
//		GetModuleHandle(NULL), // 实例句柄
//		(LPVOID) NULL); 
//
//	if (!m_hwndMain)
//	{
//		return false;
//	}
//
//	//启动后立刻更新窗口样式为透明窗体
//	UpdateClockDisplay();
//	SetTimer(m_hwndMain,1,500,NULL);
去除任务栏窗口对应按钮
//	//ModifyStyleEx (WS_EX_APPWINDOW,WS_EX_TOOLWINDOW );
//
//	DWORD dwExStyle=GetWindowLong(m_hWnd,GWL_EXSTYLE);
//	if((dwExStyle & WS_EX_LAYERED)!=WS_EX_LAYERED)
//		SetWindowLong(m_hWnd,GWL_EXSTYLE,dwExStyle^WS_EX_LAYERED);
//
//	//AnimateWindow(5000,AW_CENTER);
//
//	//用了WS_EX_LAYERED后当前窗体再也不会处理paint事件,子控件不会画出来,但是这个控件可以响应事件 。
//	//此时windows画制窗体是使用UpdateLayeredWindow这个api函数的。
//    //可以用一个空心窗体只显示该显示的控件,然后盖在你的半透明窗体上面,并处理半透明窗体的move事件,让另外一个窗体同步移动
//
//	hFuncInst = LoadLibrary("User32.DLL"); 
//	BOOL bRet=FALSE;
//	if(hFuncInst) 
//		UpdateLayeredWindow=(MYFUNC)GetProcAddress(hFuncInst, "UpdateLayeredWindow");
//	else
//	{
//		AfxMessageBox("User32.dll ERROR!");
//		exit(0);
//	}
//	//初始化gdiplus的环境
//	// Initialize GDI+.
//	m_Blend.BlendOp=0; //theonlyBlendOpdefinedinWindows2000
//	m_Blend.BlendFlags=0; //nothingelseisspecial...
//	m_Blend.AlphaFormat=1; //...
//	m_Blend.SourceConstantAlpha=255;//AC_SRC_ALPHA
//
//    ImageFromIDResource(IDR_PNGBAK1,"PNG",m_pImageClock1);
//    ImageFromIDResource(IDR_PNGBAK,"PNG",m_pImageClock);
//
//	m_BakWidth  =m_pImageClock->GetWidth();
//	m_BakHeight =m_pImageClock->GetHeight();
//
//
//
//	SetWindowText(m_hwndMain,szWindowName);
//	ShowWindow(m_hwndMain, SW_SHOW);
//	UpdateWindow(m_hwndMain);
//	return true;
//}
//
//BOOL WAGuiButtonExCtrl::ImageFromIDResource(UINT nID, LPCTSTR sTR,Image * &pImg)
//{
//	HINSTANCE hInst = AfxGetResourceHandle();
//	HRSRC hRsrc = ::FindResource (hInst,MAKEINTRESOURCE(nID),sTR); // type
//	if (!hRsrc)
//		return FALSE;
//
//	// load resource into memory
//	DWORD len = SizeofResource(hInst, hRsrc);
//	BYTE* lpRsrc = (BYTE*)LoadResource(hInst, hRsrc);
//	if (!lpRsrc)
//		return FALSE;
//
//	// Allocate global memory on which to create stream
//	HGLOBAL m_hMem = GlobalAlloc(GMEM_FIXED, len);
//	BYTE* pmem = (BYTE*)GlobalLock(m_hMem);
//	memcpy(pmem,lpRsrc,len);
//	IStream* pstm;
//	CreateStreamOnHGlobal(m_hMem,FALSE,&pstm);
//	
//	// load from stream
//	pImg=Gdiplus::Image::FromStream(pstm);
//
//	// free/release stuff
//	GlobalUnlock(m_hMem);
//	pstm->Release();
//	FreeResource(lpRsrc);
//
//}

bool WAGuiComboBoxCtrl::Create(HWND hwndParent, LPSTR szWindowName,LPSTR idName)
{
	m_hwndMain = CreateWindow(
		TEXT("COMBOBOX"), 
		NULL, // 没有标题
		// 窗口样式
		WS_CHILD | WS_VISIBLE | WS_BORDER, 
		// 位置和大小
		CW_USEDEFAULT ,
		CW_USEDEFAULT, 
		CW_USEDEFAULT, 
		CW_USEDEFAULT, 
		hwndParent, // 父窗口
		(HMENU) NULL, // 无菜单
		GetModuleHandle(NULL), // 实例句柄
		(LPVOID) NULL); 

	if (!m_hwndMain)
	{
		return false;
	}
	SetWindowText(m_hwndMain,szWindowName);
	ShowWindow(m_hwndMain, SW_SHOW);
	UpdateWindow(m_hwndMain);
	return true;
}

void WAGuiComboBoxCtrl::InsertComboBoxString(HWND hwnd,int row,LPSTR name)   
{                                                                         
	::SendMessage(hwnd,CB_INSERTSTRING,row,(LPARAM)name);
}                                                                           

void WAGuiComboBoxCtrl::SetComboBoxSelect(HWND hwnd,int row)                  
{                                                                        
    ::SendMessage(hwnd,CB_SETCURSEL,0,(LPARAM)row);	
}                                                                        
int WAGuiComboBoxCtrl::GetComboBoxSelect(HWND hwnd)                           
{                                                                        
    return ::SendMessage(hwnd,CB_GETCURSEL,0,0);
}

bool WAGuiEditCtrl::Create(HWND hwndP, LPSTR szTitle, LPSTR idName)
{
	m_hwndMain = CreateWindow(
		"EDIT", 
		NULL, // 没有标题
		// 窗口样式
		WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_BORDER |
		// 文本框样式
		ES_LEFT | ES_MULTILINE | ES_AUTOVSCROLL, 
		// 位置和大小
		CW_USEDEFAULT ,
		CW_USEDEFAULT, 
		CW_USEDEFAULT, 
		CW_USEDEFAULT, 
		hwndP, // 父窗口
		(HMENU) NULL, // 无菜单
		GetModuleHandle(NULL)/*m_hinst*/,		
		(LPVOID) NULL); // 无图标

	if (!m_hwndMain)
	{
		return false;
	}
	ShowWindow(m_hwndMain, SW_SHOW);
	UpdateWindow(m_hwndMain);
	return true;
}

void WAGuiEditCtrl::SetText(LPSTR szTextToShow)
{
	SendMessage(m_hwndMain, WM_SETTEXT, 0, (LPARAM) szTextToShow); 
}
												   
int WAGuiEditCtrl::GetEditInt(HWND hwnd)                                    
{																		   
	char buffer[64];														   
	GetWindowText(hwnd,buffer,64-1);									   
	return atoi(buffer);						   
}																		   
float WAGuiEditCtrl::GetEditFloat(HWND hwnd)                                
{																		   
	char buffer[64];														   
	GetWindowText(hwnd,buffer,64-1);									   
	return atof(buffer);						   
}																		   
																		   
LPSTR WAGuiEditCtrl::GetEditString(HWND hwnd)							   
{							
	char buffer[64];														   
	GetWindowText(hwnd,buffer,64-1);								   
	return buffer;														   
}																		   
void WAGuiEditCtrl::SetEditInt(HWND hwnd,int value)						
{																		   	
	char buffer[64];												   
	sprintf(buffer,"%d",value);											   
	SetWindowText(hwnd,buffer);	
}																		   
void WAGuiEditCtrl::SetEditFloat(HWND hwnd,float value)					
{																		   
	char buffer[64];												   
	sprintf(buffer,"%f",value);											   
	SetWindowText(hwnd,buffer);								   
}																		   
																		   
void WAGuiEditCtrl::SetEditString(HWND hwnd,LPSTR text)				   
{																		   
	SetWindowText(hwnd,text);								   
}                                                                          

bool WAGuiListBoxCtrl::Create(HWND hwndParent, LPSTR szWindowName,LPSTR idName)
{
	m_hwndMain = CreateWindow(
		TEXT("LISTBOX"), 
		NULL, // 没有标题
		// 窗口样式
		WS_CHILD | WS_VISIBLE | WS_BORDER | LBS_NOTIFY | LBS_COMBOBOX | LBS_MULTICOLUMN , 
		// 位置和大小
		CW_USEDEFAULT ,
		CW_USEDEFAULT, 
		CW_USEDEFAULT, 
		CW_USEDEFAULT, 
		hwndParent, // 父窗口
		(HMENU) NULL, // 无菜单
		GetModuleHandle(NULL)/*m_hinst*/,		
		(LPVOID) NULL); 

	if (!m_hwndMain)
	{
		return false;
	}
	SetWindowText(m_hwndMain,szWindowName);
	ShowWindow(m_hwndMain, SW_SHOW);
	UpdateWindow(m_hwndMain);
	return true;
}

void WAGuiListBoxCtrl::InsertItem(int row,LPSTR name)     
{                                                                           
	::SendMessage(m_hwndMain,LB_INSERTSTRING,row,(LPARAM)name);
}                    

void WAGuiListBoxCtrl::RemoveItem(int row)     
{                                                             
	if(row == -1)                                             
	    ::SendMessage(m_hwndMain,LB_RESETCONTENT,row,0);
	else                                                         
	    ::SendMessage(m_hwndMain,LB_DELETESTRING,row,0);
}                        

int WAGuiListBoxCtrl::GetSelectLine()                           
{                       
	//失败返回LB_ERR  
	//063 不能发送此消息给可多选的listbox,如果发送给多选listbox将返回拥有焦点的矩形所在索引,如果没有选择将返回0 
    return ::SendMessage(m_hwndMain,LB_GETCURSEL,0,0);
}

int WAGuiListBoxCtrl::GetCount()                           
{                       
	return ::SendMessage(m_hwndMain,LB_GETCOUNT,0,0);
}
int WAGuiListBoxCtrl::GetSelCount()                           
{                       
	return ::SendMessage(m_hwndMain,LB_GETSELCOUNT,0,0);
}
int WAGuiListBoxCtrl::GetSelItems()                           
{                       
	return ::SendMessage(m_hwndMain,LB_GETSELITEMS,0,0);
}
void WAGuiListBoxCtrl::GetText(LPSTR*buffer,int row)
{
    ::SendMessage(m_hwndMain,LB_GETTEXT,row,(LPARAM)buffer);
}

//=============================
bool WAGuiListViewCtrl::Create (HWND hwndParent, LPSTR szWindowName, LPSTR idName)
{
	m_hwndMain = CreateWindow (
		WC_LISTVIEW, // List View窗口类
		// 窗口标题,由于未指定 WS_TILED ,这是一个无标题的窗口
		szWindowName,
		// 窗口样式,可视,子窗口,以及List View样式
		WS_VISIBLE | WS_CHILD | LVS_REPORT | LVS_EDITLABELS,
		// 位置和大小,创建完成后使用SetWindows设置
		CW_USEDEFAULT,
		CW_USEDEFAULT,
		CW_USEDEFAULT,
		CW_USEDEFAULT,
		hwndParent,		// 父窗口
		NULL, 
		GetModuleHandle(NULL)/*m_hinst*/,		
		NULL);	// 无菜单,无图标
	if (m_hwndMain == NULL)
	{
		return NULL;
	}
	// 初始化Image List、初始化列、加入一些项
	if(InitListViewImageLists(m_hwndMain) &&
		InitListViewColumns(m_hwndMain) &&
		AddListViewItems(m_hwndMain))
	{
		return true;
	}
	DestroyWindow(m_hwndMain);
	return false;
}

/* ************************************
* BOOL InitListViewImageLists(HWND hWndListView)
* 功能	设置 List View 的 ImageList
* 参数	hWndListView,List View 控件窗口
**************************************/
BOOL WAGuiListViewCtrl::InitListViewImageLists(HWND hWndListView)
{
	HIMAGELIST himl; 
	HBITMAP hbmp; 
	// 调用 GetImageList 获得ImageList
	GetImageList(&himl);
	// 设置 List View的的 ImageList
	ListView_SetImageList(hWndListView, himl, LVSIL_SMALL);
	return TRUE;
}

/* ************************************
* BOOL InitListViewColumns(HWND hWndListView)
* 功能	设置 List View 的 分栏
* 参数	hWndListView,List View 控件窗口
* 返回值	是否成功
**************************************/
BOOL WAGuiListViewCtrl::InitListViewColumns(HWND hWndListView)
{
	char szText[256]; 
	LVCOLUMN lvc;
	DWORD i;
	// 分栏标题
	LPSTR ColNames[] = {"name", "type", "size", "time"};
	// LVCOLUMN中有效的成员
	lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
	// 填充LVCOLUMN结构
	lvc.pszText = szText;
	lvc.cx = 100;						// 长度
	lvc.iImage = 1;
	lvc.fmt = LVCFMT_LEFT;	// 向左对齐
	// 前三个
	for(i=0; i<3; i++)
	{
		//	设置栏的文本
		lvc.pszText = ColNames[i];
		lvc.iSubItem = i;
		// 调用ListView_InsertColumn插入分栏
		if (ListView_InsertColumn(hWndListView, i,	&lvc) == -1)
		{
			return FALSE;
		}
	}
	// 最后一个分栏
	lvc.cx = 200; // 长度
	lvc.fmt = LVCFMT_RIGHT; // 右对齐
	lvc.iSubItem = 3;
	lvc.pszText = ColNames[3];
	// 插入分栏
	if (ListView_InsertColumn(hWndListView, 3,	&lvc) == -1)
	{
		return FALSE;
	}
	return TRUE;
}

/* ************************************
* BOOL AddListViewItems(HWND hwndListView)
* 功能	为List View增加项
* 参数	hwndListView,父窗口
* 返回值	窗口句柄
**************************************/
BOOL WAGuiListViewCtrl::AddListViewItems(HWND hwndListView)
{
	LVITEM lvI;
	DWORD index;

	ZeroMemory (&lvI,sizeof(lvI));
	// 有效的项
	lvI.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM | LVIF_STATE;
	// 填充LVITEM
	lvI.state = 0;
	lvI.stateMask = 0;
	// 循环增加
	for (index = 0; index < 3; index++)
	{
		lvI.iItem = index;
		lvI.iImage = 0;
		lvI.iSubItem = 0;
		// 项的文本和长度
		lvI.pszText = "name1"; 
		lvI.cchTextMax = lstrlen(lvI.pszText)+1;
		// 插入项
		if(ListView_InsertItem(hwndListView, &lvI) == -1)
			return FALSE;
		// 设置子项的文本,0 based
		ListView_SetItemText(hwndListView, index, 2, "size a");
	}
	return TRUE;
}
/* ************************************
* BOOL GetImageList(HIMAGELIST * pHiml)
* 功能	TODO 增加ImageList项
* 参数	pHiml,Image List
**************************************/
BOOL WAGuiListViewCtrl::GetImageList(HIMAGELIST * pHiml)
{
	return TRUE;
}

/* ************************************
* 功能	创建一个Tree View控件,并调用InitTreeViewItems增加若干个节点
*			szWindowName,窗口标题
**************************************/
bool WAGuiTreeCtrl::Create(HWND hwndParent, LPSTR szWindowName, LPSTR idName)
{
	m_hwndMain = CreateWindowEx(0,
		WC_TREEVIEW,		
		szWindowName,	// 窗口的标题
		// 窗口样式 :可见,子窗口,可改变大小,具体窗口标题
		WS_VISIBLE | WS_CHILD | WS_SIZEBOX |  WS_TILED |
		// 附加Tree View样式
		TVS_HASBUTTONS |TVS_LINESATROOT , 
		// 默认大小和位置,后面使用SetWindows函数设置
		CW_USEDEFAULT,	
		CW_USEDEFAULT,
		CW_USEDEFAULT,
		CW_USEDEFAULT,
		hwndParent,		
		(HMENU)NULL,	
		GetModuleHandle(NULL)/*m_hinst*/,		
		NULL);		// 没有图标

	// 初始化 Image List 和节点,
	if (!InitTreeViewImageLists(m_hwndMain) ||
		!InitTreeViewItems(m_hwndMain))
	{
		DestroyWindow(m_hwndMain);
		return false;
	}
	return true;
}

/* ************************************
* BOOL InitTreeViewItems(HWND hwndTV)
* 功能	为Tree View窗口增加若干个节点
* 参数	hwndTV,Tree View控件窗口句柄
**************************************/
BOOL WAGuiTreeCtrl::InitTreeViewItems(HWND hwndTV)
{
	// 根节点1
	HTREEITEM hRoot = AddItemToTree(hwndTV, "type1", NULL,TRUE);
	// 根节点1的子节点1
	HTREEITEM hP = AddItemToTree(hwndTV, "name1", hRoot,FALSE);
	// 根节点1的子节点2
	hP = AddItemToTree(hwndTV, "name2", hRoot, TRUE);
	// 子节点2的子节点
	AddItemToTree(hwndTV, "sub1", hP,FALSE);
	// 子节点2的了节点
	AddItemToTree(hwndTV, "sub2", hP,FALSE);
	// 根节点2
	hRoot = AddItemToTree(hwndTV, "type2", NULL,TRUE);
	// 根节点2的子节点
	hP = AddItemToTree(hwndTV, "name3", hRoot, TRUE);
	// 根节点2的子子节点
	hP = AddItemToTree(hwndTV, "sub3", hP,FALSE);
	// 根节点3
	hRoot = AddItemToTree(hwndTV, "type3", NULL,TRUE);

	return TRUE;
}

/* ************************************
* AddItemToTree
* 功能	为Tree View控件增加节点
* 参数	hwndTV,Tree View控件窗口句柄
*			lpszItem,节点名(文本)
*			hParent,父节点句柄,如果为NULL,则增加根节点
*			bFolder,是否具有子节点(影响节点图标ICON)
* 返回值	创建的节点句柄
**************************************/
HTREEITEM WAGuiTreeCtrl::AddItemToTree(
						HWND hwndTV, 
						LPSTR lpszItem, 
						HTREEITEM hParent, 
						BOOL bFolder)
{
	TVITEM tvi;
	TVITEM tParent;
	TVINSERTSTRUCT tvins;
	HTREEITEM hme;
	// 填充TVITEM结构
	// 通过TVITEM的mask字段,说明那此字段是有效的
	tvi.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM;

	// 字节的文本及文本长度
	tvi.pszText = lpszItem;
	tvi.cchTextMax = sizeof(tvi.pszText)/sizeof(tvi.pszText[0]);

	// 根据bFolder参数为节点指定不同的图标
	if(bFolder)
	{
		tvi.iImage = 1;
		tvi.iSelectedImage = 2;
		tvi.cChildren = I_CHILDRENCALLBACK;
	}
	else
	{
		tvi.iImage = 3;
		tvi.iSelectedImage = 3;
		tvi.cChildren = 0;
	}

	// 填充TVINSERTSTRUCT结构
	tvins.item = tvi;
	// 新插入的子节点的位置,TVI_SORT表示按文本排序
	// 还可以是TVI_FIRST TVI_LAST等。	
	tvins.hInsertAfter = TVI_SORT;

	// 如果hParent为NULL,则插入的节点为根节点,
	// 否则hParent为其父节点
	if(hParent == NULL)
	{
		tvins.hParent = TVI_ROOT;
	}
	else
	{
		tvins.hParent = hParent;
	}
	// 调用TreeView_InsertItem宏,插入新节点
	hme = TreeView_InsertItem(hwndTV,&tvins);
	return hme;
}

// 未初始化 Tree View的 ImageList,因此节点将没有图标
// 虽然在插入节点时指定了节点的Image,但是由于ImageList为空,
// 因此图标不能显示
BOOL WAGuiTreeCtrl::InitTreeViewImageLists(HWND hwndTV)
{
	// TODO 创建 ImageLists 
	// TODO 设置 ImageLists 项
	// TODO 使用 TreeView_SetImageList 设置Tree View的 Image List
	return TRUE;
}

//implement these if we want event feedback from Flash Scripting
//DShockwaveFlashEvents
HRESULT STDMETHODCALLTYPE FlashCmdRecv::OnReadyStateChange(long newState)
{
	return S_OK;
}
HRESULT STDMETHODCALLTYPE FlashCmdRecv::OnProgress(long percentDone)
{
	return S_OK;
}
HRESULT STDMETHODCALLTYPE FlashCmdRecv::FSCommand(BSTR command, BSTR args)
{
	return m_ctrl->FSCommand ( command, args );
}
HRESULT STDMETHODCALLTYPE FlashCmdRecv::FlashCall(BSTR request)
{
	return S_OK;
}

//IDispatch Impl
HRESULT STDMETHODCALLTYPE FlashCmdRecv::GetTypeInfoCount(UINT __RPC_FAR *pctinfo)
{
	return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE FlashCmdRecv::GetTypeInfo( 
	/* [in] */ UINT iTInfo,
	/* [in] */ LCID lcid,
	/* [out] */ ITypeInfo __RPC_FAR *__RPC_FAR *ppTInfo)
{
	return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE FlashCmdRecv::GetIDsOfNames( 
	/* [in] */ REFIID riid,
	/* [size_is][in] */ LPOLESTR __RPC_FAR *rgszNames,
	/* [in] */ UINT cNames,
	/* [in] */ LCID lcid,
	/* [size_is][out] */ DISPID __RPC_FAR *rgDispId)
{
	return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE FlashCmdRecv::Invoke( 
	/* [in] */ DISPID dispIdMember,
	/* [in] */ REFIID riid,
	/* [in] */ LCID lcid,
	/* [in] */ WORD wFlags,
	/* [out][in] */ DISPPARAMS __RPC_FAR *pDispParams,
	/* [out] */ VARIANT __RPC_FAR *pVarResult,
	/* [out] */ EXCEPINFO __RPC_FAR *pExcepInfo,
	/* [out] */ UINT __RPC_FAR *puArgErr)
{
	//这里可以收到FSCommand消息回调
	switch (dispIdMember)
	{
	case 0xfffffd9f:
		printf("Invoke-OnReadyStateChange--%d\n",pDispParams->rgvarg->intVal);
		break;
	case 0x000007a6:
		printf("Invoke-OnProgress\n");
		break;
	case 0x00000096:
		m_ctrl->FSCommand ( pDispParams->rgvarg[1].bstrVal, pDispParams->rgvarg[0].bstrVal );
		//printf("Invoke-FSCommand\n");
		break;
	case 0x000000c5:
		printf("Invoke-FlashCall\n");
		break;
	default:;
	}

	return S_OK;

}
//IUnknown Impl
HRESULT STDMETHODCALLTYPE FlashCmdRecv::QueryInterface(REFIID riid, void ** ppvObject)
{
	if (IsEqualGUID(riid, __uuidof(_IShockwaveFlashEvents)/*DIID__IShockwaveFlashEvents*/))
		*ppvObject = (void*)dynamic_cast<_IShockwaveFlashEvents *>(this);
	else
	{
		*ppvObject = 0;
		return E_NOINTERFACE;
	}
	if (!(*ppvObject))
		return E_NOINTERFACE; //if dynamic_cast returned 0
	m_iRef++;
	return S_OK;
}

ULONG STDMETHODCALLTYPE FlashCmdRecv::AddRef()
{
	m_iRef++;
	return m_iRef;
}

ULONG STDMETHODCALLTYPE FlashCmdRecv::Release()
{
	m_iRef--;
	return m_iRef;
}

WAGuiFlashCtrl* WAGuiFlashCtrl::testThis;
bool WAGuiFlashCtrl::Create(HWND hwndParent, LPSTR szWindowName, LPSTR idName)
{
    LPAtlAxWinInit    AtlAxWinInit    = (LPAtlAxWinInit)   GetProcAddress(LoadLibrary("atl"),"AtlAxWinInit"); // Atl.dll v 3.0 is part of the windows
    LPAtlAxGetControl AtlAxGetControl = (LPAtlAxGetControl)GetProcAddress(LoadLibrary("atl"),"AtlAxGetControl"); 
    LPAtlAxAttachControl AtlAxAttachControl = (LPAtlAxAttachControl)GetProcAddress(LoadLibrary("atl"),"AtlAxAttachControl"); 

	HRESULT  hr = AtlAxWinInit(); 
//    m_hwndMain = CreateWindow("AtlAxWin","d:\\test.swf",
//		                       WS_VISIBLE|WS_CHILD,
//							   0,
//							   0,
//							   300,
//							   300,
//							   hwndParent,0,0,0); 
//
//	SetRect( 0,0,300,300);
//
//    IUnknown*        unkn;  
//	IWebBrowser2*    brow;          
//    IShockwaveFlash* flash=0;      
//
//	hr = AtlAxGetControl(m_hwndMain,&unkn);
//	hr = unkn->QueryInterface(__uuidof(IWebBrowser2),(void**)&brow);
//    IDispatch*      disp;              
	MsgLoopWhile( !brow->get_Document(&disp) && !disp );         // Document loading loop
//    //IHTMLDocument2* html;          hr = disp->QueryInterface(__uuidof(IHTMLDocument2),(void**)&html);
//    //IHTMLElementCollection* elems; hr = html->get_embeds(&elems); VARIANT id; VariantInit(&id);
//    //MsgLoopWhile( elems && !elems->item(id,id,&disp) && !disp ); // Document parsing loop
//	hr = unkn->QueryInterface(__uuidof(IShockwaveFlash),(void**)&flash);
//	//hr = disp->QueryInterface(__uuidof(IShockwaveFlash),(void**)&flash);
//    
//	BSTR  val,var=L"MyEvent";  
//	//hr = flash->GetVariable(var,&val); 
// //   long frame;                
//	//hr = flash->CurrentFrame(&frame);  

	HWND ctrl = CreateWindowEx(0,"AtlAxWin",0, 
								WS_VISIBLE|WS_CHILD,
								   0,
								   0,
								   300,
								   300,
								   hwndParent,0,0,0); 
	m_hwndMain = ctrl;
	SetRect( 0,0,300,300);

	hr = CoCreateInstance(__uuidof(ShockwaveFlash),0,CLSCTX_ALL, __uuidof(IShockwaveFlash), (void **)&flash); 
	hr = AtlAxAttachControl(flash,ctrl,0);
	hr = flash->QueryInterface(__uuidof(IViewObjectEx),(void **)&view);

    hr = flash->QueryInterface(IID_IConnectionPointContainer, (LPVOID*)&pCPC);
    hr = pCPC->FindConnectionPoint(
		__uuidof(_IShockwaveFlashEvents/*ShockwaveFlashObjects::DShockwaveFlashEvents*/), &m_pCP); 
	m_cmdRecv.m_ctrl = this;
	hr = m_pCP->Advise((LPUNKNOWN)&m_cmdRecv, &m_dwCookie);  
    //todo: unAdvise and release interface

	hr = flash->put_Movie(L"d:\\test.swf");
	//hr = flash->put_WMode(L"Transparent"); 
	//hr = flash->put_WMode(L"Opaque"); 
	hr = flash->put_WMode(L"Transparent windowless");
    hr = flash->put_BackgroundColor(100);
	hr = view->Draw(DVASPECT_THUMBNAIL, -1, 0, 0, 0, GetDC(ctrl), 0, 0, 0, 0);

	BSTR  val,var=L"MyEvent";  
	hr = flash->GetVariable(var,&val); 
	BSTR out[256];
    hr = flash->CallFunction(L"<invoke name=\"SetProcessBar\">\
							<arguments>\
							<string>这是C++调用flash的响应</string>\
							</arguments>\
							</invoke>",out);  
	 //   long frame;                
		//hr = flash->CurrentFrame(&frame);  
	return true;


//HWND ctrl = CreateWindowEx(0,"AtlAxWin",0,0,0,0,GetSystemMetrics(SM_CXSCREEN),GetSystemMetrics(SM_CYSCREEN),0,0,0,0);
//IShockwaveFlash* flash=0; hr = CoCreateInstance(__uuidof(ShockwaveFlash),0,CLSCTX_ALL, __uuidof(IShockwaveFlash), (void **)&flash); 
//                          hr = flash->put_WMode(L"transparent"); 
//                          hr = AtlAxAttachControl(flash,ctrl,0);
//IViewObjectEx*    view=0; hr = flash->QueryInterface(__uuidof(IViewObjectEx),(void **)&view);
//                          hr = flash->put_Movie(L"c:\\WINDOWS\\Help\\Tours\\mmTour\\segment2.swf");
//... 
 In msg loop update background and render (to 2nd visible window) 
//hr = view->Draw(DVASPECT_CONTENT, 0, 0, 0, 0, GetDC(hwnd), 0, 0, 0, 0);

}
HRESULT STDMETHODCALLTYPE WAGuiFlashCtrl::FSCommand (BSTR command,BSTR args )
{
	std::wstring cmd = command;
	std::wstring arg = args;

	//具化:使用虚的或代理模式
	//正常应该是具化FlashCmdRecv,但是它继承了虚基类
	//既然FlashCmdRecv不再具有具化功能应该可以合并到WAGuiFlashCtrl中,而再写一个不继承虚基类的cmdrecv
	if( cmd == L"click")
	{
		//点击了充值服务按钮
		//如果不想太多的if 可以用函数指针
		//先测试走通,结构可以再优化
		if( args == L"充值服务")
		{
			//MessageBox(L"c++:充值服务!");
		}

		//if( args == L"进入游戏")
		{
			BSTR out[256];
		    flash->CallFunction(L"<invoke name=\"SetProcessBar\">\
										<arguments>\
										<string>这是C++调用flash的响应</string>\
										</arguments>\
										</invoke>",out);  
		}
	}
	//else if( 0 == strcmp(command,"create_html") )
	//{
	//	//std::string str = args;
	//	//std::vector<std::string> res;
	//	//StrSplit(str,",",res);
	//	//
	//	//m_html.Create(m_hWnd,atoi(res[0].c_str()),
	//	//	                 atoi(res[1].c_str()),
	//	//					 atoi(res[2].c_str()),
	//	//					 atoi(res[3].c_str()));
	//	_root.CommandToHost("create_html",""+this._x +","+this._y +","+this._width+","+this._height+",www.163.com");
	//	//m_html.Navigate(res[4].c_str());
	//}

	return S_OK;
}


LRESULT CALLBACK MainWndProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
{
	LRESULT rt;
	WAGuiDialog* pWnd = (WAGuiDialog*)GetWindowLong(hwnd, GWL_USERDATA);
	if(pWnd) 
	{
		rt = pWnd->WinProc(uMsg, wParam, lParam);
	}
	else 
	{
	    rt = DefWindowProc(hwnd, uMsg, wParam, lParam);
	}
	return rt;
}

WNDCLASSEX WAGuiDialog::wcx;
bool WAGuiDialog::Init()
{
	wcx.cbSize = sizeof(wcx); // WNDCLASSEX结构的大小
	wcx.style = CS_HREDRAW | CS_VREDRAW; // 如果大小改变了重绘窗口
	wcx.lpfnWndProc = MainWndProc; // 窗口消息处理函数
	wcx.cbClsExtra = 0; // 附加窗口类内存
	wcx.cbWndExtra = 4; // 附加窗口实例内存,存放 WAGuiDialog的this指针
	wcx.hInstance = GetModuleHandle(NULL); // 应用程序实例
	wcx.hIcon = NULL;//LoadIcon(NULL,	MAKEINTRESOURCE(IDI_ICON_MAIN)); // 图标
	wcx.hCursor = NULL;//LoadCursor(NULL,	IDC_ARROW); // 鼠标指针
	wcx.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); // 背景画刷
	wcx.lpszMenuName = NULL;//MAKEINTRESOURCE(IDR_MENU_MAIN); // 菜单资源
	wcx.lpszClassName = "DialogWClass"; // 窗口类名
	wcx.hIconSm = (HICON)LoadImage(GetModuleHandle(NULL), // 小图标
		NULL,//MAKEINTRESOURCE(IDI_ICON_MAIN),
		IMAGE_ICON,
		GetSystemMetrics(SM_CXSMICON),
		GetSystemMetrics(SM_CYSMICON),
		LR_DEFAULTCOLOR);
	// 注册窗口类,返回
	return RegisterClassEx(&wcx);
}

bool WAGuiDialog::Create(HWND hwndParent, LPSTR szWindowName,LPSTR idName)
{
	/*
	窗口风格常量: 
	WS_BODER             窗口具有细线边框 
	WS_CAPTION           窗口具有标题栏(包含 WS_BODER) 
	WS_CHILD             创建一个子窗口(此风格不能与 WS_POPUP 一起使用 ) 
	WS_CHILDWINDOW       与 WS_CHILD 相同 
	WS_CLIPCHILDREN      当在父窗口中画图时,绕开子窗口占有的区域。 
	WS_CLIPSBLINGS       裁剪相互关联的子窗口,使一个特殊 的子窗口收到 WS_PAINT 消息时,仅对自身窗口起作用。此式样仅适合具有 WS_CHILD 风格的窗口。 
	WS_DISABLED          创建一个开始时禁止的窗口 
	WS_DLGFRAME          创建一个具有某种式样的边框的窗口,该式样一般与对话框一起使用,具有该式样的窗口不能有一个标题栏。 
	WS_GROUP             指定一组控制中的第一个控制,具有该式样控制的下一个控制终止当前控制组,并且开始下一个控制组。 
	WS_HSCROLL           窗口具有水平滚动条 
	WS_VSCROOL           窗口具有垂直滚动条 
	WS_MAXIMIZE          窗口初始时最大化 
	WS_MINIMIZE          窗口初始时最小化 
	WS_MINIMIZEBOX       窗口具有最小化按钮 
	WS_MAXIMIZEBOX       窗口具有最大化按钮 
	WS_OVERLAPPED        重叠 式窗口,该式样窗口 带有一个标题栏和边框 
	WS_OVERLAPPEDWINDOW  具有WS_OVERLAPPED,WS_CAPTION,WS_SYSMENU,WS_THICKFRAM, WS_MINIMIZEBOX,WS_MAXIMIZEBOX 式样的重叠式窗口 
	WS_POPUP             弹出式窗口,不能与 WS_CHILD 一起使用 
	WS_POPUPWINDOW       具有 WS_BODER,WS_POPUP,WS_SYSMENU 式样的弹出式窗口。为了使 SYSTEM 菜单(也叫 CONTROL 菜单可见),必须将 WS_CAPTION与 WS_POPUPWINDOW 式样组合使用。 
	WS_SYSMENU           具有 SYSTEM 菜单栏,还必须指定 WS_CAPTION 式样 WS_THICKFRAME 具有可调边框 WS_VISIBLE 窗口初始时可见 扩展窗口风格常量 
	WS_EX_ACCEPTFILES    窗口可接收拖放文件 
	WS_EX_DLGMODALFRAME  具有双线边框 
	WS_EX_NOPARENTNOTIFY 当一个子窗口创建或取消时,不向其父窗口发送
	WM_PARENTNOTIFY      消息 WS_EX_TOPMOST 窗口放在所有非顶层窗口之上,即使窗口 不工作。 支持 3D 外观的扩展风格 
	WS_EX_CLIENTEDGE     为应用程序的主工作空间创建一个下陷的客户区,例如一个字处理程序的文本窗口 
	WS_EX_STATICEDGE     为只用于输出的窗口创建下陷的客户区。
	*/
	m_hwndParent = hwndParent;
	m_hwndMain = CreateWindow(
		"DialogWClass", // 窗口类名,使用之前注册的主窗口类
		szWindowName, // 窗口名,显示在窗口标题栏上的字符串
		WS_CHILD|WS_VISIBLE|WS_BORDER|WS_VSCROLL|WS_HSCROLL|WS_OVERLAPPEDWINDOW/*WS_DLGFRAME*/|WS_CLIPCHILDREN,
		CW_USEDEFAULT, // 水平位置(默认)
		CW_USEDEFAULT, // 垂直位置(默认)
		800, // 宽
		600, // 高
		m_hwndParent, 
		NULL,//(HMENU) LoadMenu(m_hinst,MAKEINTRESOURCE(IDR_MENU_MAIN)), // 菜单
		GetModuleHandle(NULL)/*m_hinst*/,
		(LPVOID) NULL); // 无窗口创建数据
		//(LPVOID) this); // 无窗口创建数据

	if (!m_hwndMain)
		return FALSE;
    SetWindowLong(m_hwndMain, GWL_USERDATA, (LONG)this);

	SCROLLINFO  si;   
	si.cbSize = sizeof (si);
	si.fMask  = SIF_ALL;
	GetScrollInfo (m_hwndMain, SB_VERT, &si);
	si.nMin = 0;
	si.nMax = 5;//m_Buffer.size();
	si.nPos += 1;
	si.fMask  = SIF_RANGE | SIF_POS;
	SetScrollInfo(m_hwndMain, SB_VERT, &si, TRUE);
	ScrollWindow (m_hwndMain, 0, 15 * si.nPos, NULL, NULL);
	Invalidate();     

	return TRUE;
}

LRESULT WAGuiDialog::WinProc(UINT uMsg, WPARAM wParam,LPARAM lParam)
{
	SCROLLINFO  si;   
	RECT rect;
	GetClientRect(m_hwndMain, &rect);
    int iVertPos;

	switch (uMsg)
	{
	//case WM_CREATE:	
	//	break;
	//case WM_PAINT:	
	//	break;
	//case WM_SIZE:	
	//	//RECT rcClient;
	//	//GetClientRect(m_hwndMain, &rcClient);
	//	//SetWindows(&rcClient);
	//	break;
	//case WM_LBUTTONDOWN:		
	//	break;
	//case WM_SHOWWINDOW: 
    //case WM_KEYDOWN: 
	//	break;
  case WM_VSCROLL:
		si.cbSize = sizeof (si);
		si.fMask  = SIF_ALL;
		GetScrollInfo (m_hwndMain, SB_VERT, &si) ;
		iVertPos = si.nPos ;
		switch (LOWORD (wParam))
		{
			case SB_TOP:
				si.nPos = si.nMin ;
				break ;
			case SB_BOTTOM:
				si.nPos = si.nMax ;
				break ;
			case SB_LINEUP:
				si.nPos -= 1 ;
				break ;
			case SB_LINEDOWN:
				si.nPos += 1 ;
				break ;
			case SB_PAGEUP:
				si.nPos -= si.nPage ;
				break ;
			case SB_PAGEDOWN:
				si.nPos += si.nPage ;
				break ;
			case SB_THUMBTRACK:
				si.nPos = si.nTrackPos ;
				break ;
			default:
				break ;         
		}
		//Set the position and then retrieve it.  Due to adjustments
		//by Windows it may not be the same as the value set.
		si.fMask = SIF_POS ;
		SetScrollInfo (m_hwndMain, SB_VERT, &si, TRUE) ;
		GetScrollInfo (m_hwndMain, SB_VERT, &si) ;
		// If the position has changed, scroll the window and update it
		if (si.nPos != iVertPos)
		{                    
			ScrollWindow (m_hwndMain, 0, 10 * (iVertPos - si.nPos), NULL, NULL) ;
			Invalidate(); 
		}
		break ;
		// NOTIFY,通常由控件发送给父窗口
	case WM_NOTIFY:
		OnChildWindowsNotify((PVOID)lParam);
		break;
	case WM_DESTROY:
		//ShowWindow(m_hwndMain,SW_HIDE); 
		break;
	case WM_LBUTTONDOWN:
		m_lastMouseDownPt.x = LOWORD(lParam);
		m_lastMouseDownPt.y = HIWORD(lParam);
		m_mousePressed = true;
		break;
	case WM_LBUTTONUP:
		m_mousePressed = false;
		break;

	case WM_MOUSEMOVE:

		//InvalidateRect (m_hwndMain, 0, TRUE);

		POINT pt;
		int ret;
		HDC hDC;
		pt.x=LOWORD(lParam);
		pt.y=HIWORD(lParam);
		hDC=GetDC(m_hwndMain);
		//绘制出鼠标拖放的矩形

		if(m_mousePressed)
		    Rectangle(hDC,m_lastMouseDownPt.x,m_lastMouseDownPt.y,pt.x,pt.y);

		for(int i=0;i<m_ctrls.size();i++)
		{
			RECT rt;
			GetWindowRect(m_ctrls[i]->m_hwndMain,&rt);
			//ScreenToClient(m_ctrls[i]->m_hwndMain,);
			if (PtInRect(&rt,pt))
			{
				SetFocus(m_ctrls[i]->m_hwndMain);
			}
		}
			
		break;
	case WM_CLOSE:
		//在窗口关闭时,同样以动画的方式结束
		AnimateWindow(m_hwndMain,500,AW_CENTER|AW_HIDE);
		break;
		// 菜单项被选中,或按钮被点击
	case WM_COMMAND:
		break;
	default:
		return DefWindowProc(m_hwndMain, uMsg, wParam, lParam);
		break;
	}
	return DefWindowProc(m_hwndMain, uMsg, wParam, lParam);
};

void WAGuiDialog::Invalidate()
{
	//注意 RDW_UPDATENOW
	RedrawWindow(m_hwndMain,NULL,NULL,RDW_INVALIDATE|RDW_ALLCHILDREN|RDW_UPDATENOW/*|RDW_ERASE*/|RDW_FRAME);
}

HWND WAGuiDialog::CreateButton(HWND hwndParent, LPSTR szWindowName,LPSTR idName,DWORD types)
{
	WNDCLASSEX wcx;
	HWND hwnd;

	hwnd = CreateWindow(
		TEXT("button"), 
		NULL, // 没有标题
		// 窗口样式
		WS_CHILD | WS_VISIBLE | WS_BORDER | BS_NOTIFY | types, 
		// 位置和大小
		CW_USEDEFAULT ,
		CW_USEDEFAULT, 
		CW_USEDEFAULT, 
		CW_USEDEFAULT, 
		hwndParent, // 父窗口
		(HMENU) NULL, // 无菜单
		GetModuleHandle(NULL), // 实例句柄
		(LPVOID) NULL); 

	if (!hwnd)
	{
		return NULL;
	}
	SetWindowText(hwnd,szWindowName);
	ShowWindow(hwnd, SW_SHOW);
	UpdateWindow(hwnd);
	return hwnd;
}

bool WAGuiDialog::LoadFromFile(char* _filename)
{
	//Free();
	BasicExcel excel;
	excel.Load(_filename);	
	BasicExcelWorksheet* sheet = excel.GetWorksheet("Sheet1");
	if (sheet == NULL) return 0;
	size_t maxRows = sheet->GetTotalRows();
	size_t maxCols = sheet->GetTotalCols();
	PARSEHEADER(sheet);
	//char*  sheetName = sheet1->GetAnsiSheetName() 
    //自身
    SetRect(sheet->Cell(1,NameCol["x"])->GetInteger(),
			                sheet->Cell(1,NameCol["y"])->GetInteger(),
							sheet->Cell(1,NameCol["width"])->GetInteger(),
							sheet->Cell(1,NameCol["height"])->GetInteger());

	m_strCtrls.clear();
	//子控件
	m_ctrls.resize(maxRows - 2);
	for(unsigned int i=0; i<m_ctrls.size(); ++i)
	{
		switch(sheet->Cell(i+2,NameCol["type"])->GetInteger())
		{
		case CT_STATIC:
			//m_ctrls[i] = new WAGuiEditCtrl;
			break;
		//case CT_BUTTON:
		    //m_ctrls[i] = new GuiButtonCtrl;
		//    break;
		case CT_EDIT:
			m_ctrls[i] = new WAGuiEditCtrl;
			break;
		case CT_LISTBOX:
			m_ctrls[i] = new WAGuiListBoxCtrl;
			break;
		case CT_LISTCTRL:
			m_ctrls[i] = new WAGuiListViewCtrl;
			break;
		case CT_TREE:
			m_ctrls[i] = new WAGuiTreeCtrl;
			break;
		case CT_DIALOG:
			m_ctrls[i] = new WAGuiDialog;
			break;
		default:
			break;
		}
		m_ctrls[i]->Create(m_hwndMain,"");
		m_ctrls[i]->SetRect(sheet->Cell(i+2,NameCol["x"])->GetInteger(),
			                sheet->Cell(i+2,NameCol["y"])->GetInteger(),
							sheet->Cell(i+2,NameCol["width"])->GetInteger(),
							sheet->Cell(i+2,NameCol["height"])->GetInteger());
		m_ctrls[i]->m_idName = sheet->Cell(i+2,NameCol["id_name"])->GetString();
		if(m_ctrls[i]->m_idName != "")
			m_strCtrls.insert(std::make_pair(m_ctrls[i]->m_idName,m_ctrls[i]));

	}

	MapCtrl();
	UpdateWindow(m_hwndMain);
}

/* ************************************
* VOID APIENTRY DisplayContextMenu(HWND hwnd, POINT pt)
* 功能	在屏幕上显示弹出菜单
* 参数	hwnd,菜单所属窗口
*			pt,菜单位置(相对于屏幕)
**************************************/
VOID APIENTRY WAGuiDialog::DisplayContextMenu(HWND hwnd, POINT pt)
{
	HMENU hmenu; // 顶级菜单
	HMENU hmenuTrackPopup; // 弹出菜单

	// 加载菜单资源,获得菜单句柄
	if ((hmenu = LoadMenu(GetModuleHandle(NULL), MAKEINTRESOURCE(IDR_MENU_POPUP))) == NULL)
		return;

	// 获得菜单资源中的子菜单,所显示的是菜单资源中的子菜单
	hmenuTrackPopup = GetSubMenu(hmenu, 0);
	// 弹出
	TrackPopupMenuEx(hmenuTrackPopup,
		TPM_LEFTALIGN | TPM_RIGHTBUTTON,
		pt.x, pt.y, hwnd, NULL);
	// 完成,释放相关资源
	DestroyMenu(hmenu);
}
											   
bool WAGuiDialog::GetCheckBool(HWND hwnd)								   
{																		   
	if(::SendMessage(hwnd,BM_GETCHECK,	0,	0)==TRUE)  
		return true;													   
	else																   
		return false;													   
}																		   

void WAGuiDialog::SetCheckBool(HWND hwnd,bool value)					
{																		   
	::SendMessage(hwnd,BM_SETCHECK,	int(value),	0);    
}																		   
															   
void WAGuiDialog::InsertListCtrlColumn(HWND hwnd,int row,LPSTR name)	   
{                                                                          
    LVCOLUMN   column;													   
    column.pszText   =  name;								   
	::SendMessage(hwnd,LVM_INSERTCOLUMN,row,(LPARAM)(LPLVCOLUMN)&column);
}	                                                                      
                          
//弹出“浏览文件夹”对话框
DWORD WAGuiDialog::Browse(HWND hwnd) 
{
	// 用于保存路径
	CHAR szRoot[MAX_PATH];
	CHAR szChoose[MAX_PATH];
	CHAR szDisplayName[MAX_PATH];
	// 相关变量
	LPITEMIDLIST pidlRoot = NULL;
	LPITEMIDLIST pidlSelected = NULL;
	BROWSEINFO bi = {0};
	LPMALLOC pMalloc = NULL;

	// “浏览文件夹”的根路径,开发人员可根据情况选择,比如只浏览“我的文档”。
	SHGetFolderLocation(NULL, CSIDL_DESKTOP, NULL, 0, &pidlRoot);
	SHGetPathFromIDList(pidlRoot,szRoot);
	// 填充 BROWSEINFO 结构
	bi.hwndOwner = hwnd;
	bi.pidlRoot = pidlRoot;
	bi.pszDisplayName = szDisplayName;
	bi.lpszTitle = "Choose a target";
	bi.ulFlags = 0;
	bi.lpfn = NULL;
	bi.lParam = 0;
	// 弹出对话框
	pidlSelected = SHBrowseForFolder(&bi);
	// DisplayName
	MessageBox(NULL,szDisplayName,"Display Name:",MB_OK);
	// 选择的文件夹
	SHGetPathFromIDList( pidlSelected, szChoose );
	MessageBox(NULL,szChoose,"Choose:",MB_OK);
	// 释放
	ILFree(pidlRoot);

    OPENFILENAME g_ofn;
	g_ofn.hwndOwner	=hwnd;
	g_ofn.lpstrFile	=szChoose; //need gloabl or exter
	g_ofn.lpstrTitle="Load MSL File";
	g_ofn.lpstrFilter="MSL Spell Files (*.MSL)\0*.MSL\0All Files (*.*)\0*.*\0\0";
	g_ofn.lpstrDefExt="MSL";

	//Ask for filename
	if(!GetOpenFileName(&g_ofn))
		return FALSE;

	return 0;
}

/* VOID DoPaint(HWND hWnd, DWORD dwMode)
* 功能 将位图(全局变量ghBitmap)显示在界面上
* DWORD dwMode,模式,是否拉申
*/
VOID WAGuiDialog::DoPaint(HWND hWnd, HBITMAP bitmap,DWORD dwMode)
{
	PAINTSTRUCT ps;
	RECT rect;
	HDC hdcMem;
	BITMAP bm;
	// BeginPaint
	HDC hDC = BeginPaint(hWnd, &ps);
	// 获取窗口的Client区域,用于显示位图
	GetClientRect(hWnd, &rect);

	// 设置拉申模式
	SetStretchBltMode(hDC, HALFTONE);
	// 将BITMAP对象选择入内存DC
	hdcMem = CreateCompatibleDC(hDC);
	SelectObject(hdcMem, bitmap);
	if (bitmap)
	{
		// 获取DIB属性
		if (GetObject(bitmap, sizeof(BITMAP), &bm))
		{
			// 判断参数示:是否根据显示窗口大小拉申位图
			// 采用不同的方面将内存DC StretchBl t至窗口Client区域DC
			if(1)//dwMode == CAP_SHOW_MODE_STRTCH)
			{
				StretchBlt(hDC, 0, 0, rect.right, rect.bottom,
					hdcMem, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY);
			}
			else
			{
				// 不拉伸,计算显示的位置,将其显示在Client的中央
				INT ixStart = (rect.right - rect.left - bm.bmWidth)/2;
				INT iyStart = (rect.bottom - rect.top - bm.bmHeight)/2;
				ixStart = ixStart < 0 ? 0 : ixStart;
				iyStart = iyStart < 0 ? 0 : iyStart;
				BitBlt(hDC, 0, 0, rect.right, rect.bottom,
					hdcMem,-ixStart,-iyStart, SRCCOPY);
			}
			DeleteDC(hdcMem);
		}
	}
	// 如果没有位图,则使用Brush填充
	else
	{
		PatBlt(hDC, 0, 0, rect.right, rect.bottom, BLACKNESS);
	}
	// EndPaint
	EndPaint(hWnd, &ps);
}

#include "WAGui.h"
#include "resource.h"

HFONT logfont_song[16];
HFONT logfont_yahei[16];

bool WAGuiTestDialog::Create(HWND hwndParent, LPSTR szWindowName,LPSTR idName)
{
	WAGuiDialog::Create(hwndParent,szWindowName,idName);

	LOGFONT logfont;
	logfont.lfHeight = 12;
	logfont.lfWidth = 0;
	logfont.lfEscapement = 0;
	logfont.lfOrientation = 0;
	logfont.lfWeight = 100;//FW_BOLD;//FW_DONTCARE;
	logfont.lfItalic = FALSE;
	logfont.lfUnderline = FALSE;
	logfont.lfStrikeOut = FALSE;
	logfont.lfCharSet = GB2312_CHARSET;
	logfont.lfOutPrecision = OUT_DEFAULT_PRECIS;
	logfont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
	logfont.lfQuality = DEFAULT_QUALITY;
	logfont.lfPitchAndFamily = DEFAULT_PITCH;
	strcpy(logfont.lfFaceName,"宋体");
	for(int i=0;i<12;i++)
	{
		logfont.lfHeight = (4+i)*2;
	    logfont_song[i] = CreateFontIndirect(&logfont);
	}
	strcpy(logfont.lfFaceName,"微软雅黑");
    for(int i=0;i<12;i++)
	{
		logfont.lfHeight = (4+i)*2 *1.4;
	    logfont_yahei[i] = CreateFontIndirect(&logfont);
	}
	InvalidateRect (m_hwndMain, 0, TRUE);

	//return true;

	RECT rect;
    m_hwndButton   = CreateButton(m_hwndMain,"sss");

	LoadFromFile("testDialog.xls");

	//GetWindowRect()   得到的是在屏幕坐标系下的RECT;(即以屏幕左上角为原点) 
	//GetClientRect()   得到的是在客户区坐标系下的RECT;   (即以所在窗口左上角为原点) 
	//ScreenToClient()   就是把屏幕坐标系下的RECT坐标转换为客户区坐标系下的RECT坐标。 
	//注意了!!
	//第二个函数和它不同,它只获得了客户区的大小,因此得到的结果总是这样CRect(0,0,width,height);  

	LPSTR lpszLatin =  "Lorem ipsum dol\n L \n d \n o \n ipsum \n "
		               "Lorem ipsum dol\n L \n d \n o \n ipsum \n "
					   "Lorem ipsum dol\n L \n d \n o \n ipsum \n "
					   "Lorem ipsum dol\n L \n d \n o \n ipsum \n "
					   "Lorem ipsum dol\n L \n d \n o \n ipsum \n "
					   "Lorem ipsum dol\n L \n d \n o \n ipsum \n "
					   "Lorem ipsum dol\n L \n d \n o \n ipsum \n "; 
	m_hwndEdit->SetText(lpszLatin);
	ShowWindow(m_hwndMain, 1);
	UpdateWindow(m_hwndMain);

	m_hwndListBox->InsertItem(0,"0");
	m_hwndListBox->InsertItem(0,"1");
	m_hwndListBox->InsertItem(0,"2");


	m_hwndFlash = new WAGuiFlashCtrl;
	m_hwndFlash->Create(m_hwndMain,"");

    //HBITMAP hBmp;
	//hBmp = (HBITMAP)LoadImage(/*hInstance*/0,"back.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE/*LR_CREATEDIBSECTION*/);
	//if (hBmp)
	//{
	//		//BITMAP bm;
	//		//GetObject(hBmp, sizeof(bm), &bm);
	//		//hWnd = CreateWindow(szClassName, NULL, WS_POPUP, 0, 0, bm.bmWidth, bm.bmHeight, NULL, NULL, hInstance, NULL);
	//		HRGN h = WATool::BitmapToRegion(hBmp);
	//		if (h)
	//			SetWindowRgn(m_hwndMain, h, TRUE);
	//		UpdateWindow(m_hwndMain);
	//}

	//WATool::SetTransparent(m_hwndParent,210,true);

	return true;
}

void WAGuiTestDialog::MapCtrl()
{
    MAPCTRL("Tree01",m_hwndTreeView);
	MAPCTRL("ListView01",m_hwndListView);
	MAPCTRL("ListBox01",m_hwndListBox);
	MAPCTRL("Edit01",m_hwndEdit);

}

#include "ThreadOperator.h"

#define ID_FILE_EXIT 9001
#define ID_STUFF_GO 9002
LRESULT WAGuiTestDialog::WinProc(UINT uMsg, WPARAM wParam,LPARAM lParam)
{	
	HDC          hdc ;
	PAINTSTRUCT  ps ;
	HMENU        hMenu, hSubMenu;
    HICON        hIcon, hIconSm;
	HGDIOBJ      old;

	switch (uMsg)
	{
	case WM_CREATE:

            hMenu = CreateMenu();

            hSubMenu = CreatePopupMenu();
            AppendMenu(hSubMenu, MF_STRING, ID_FILE_EXIT, "E&xit");
            AppendMenu(hMenu, MF_STRING | MF_POPUP, (UINT)hSubMenu, "&File");

            hSubMenu = CreatePopupMenu();
            AppendMenu(hSubMenu, MF_STRING, ID_STUFF_GO, "&Go");
            AppendMenu(hMenu, MF_STRING | MF_POPUP, (UINT)hSubMenu, "&Stuff");

            SetMenu(m_hwndMain, hMenu);

            //hIcon = LoadImage(NULL, "menu_two.ico", IMAGE_ICON, 32, 32, LR_LOADFROMFILE);
            //if(hIcon)
            //    SendMessage(m_hwndMain, WM_SETICON, ICON_BIG, (LPARAM)hIcon);
            //else
            //    MessageBox(m_hwndMain, "Could not load large icon!", "Error", MB_OK | MB_ICONERROR);

            //hIconSm = LoadImage(NULL, "menu_two.ico", IMAGE_ICON, 16, 16, LR_LOADFROMFILE);
            //if(hIconSm)
            //    SendMessage(m_hwndMain, WM_SETICON, ICON_SMALL, (LPARAM)hIconSm);
            //else
            //    MessageBox(m_hwndMain, "Could not load small icon!", "Error", MB_OK | MB_ICONERROR);

	case WM_PAINT:

		InvalidateRect (hwnd, &rect, TRUE) ;
		DoPaint(m_hwndMain,G_GuiMgr.m_hBitmap,0);

		//hdc = BeginPaint (m_hwndMain, &ps) ;
		//SelectObject (hdc, GetStockObject (SYSTEM_FIXED_FONT)) ;
		SetBkMode (hdc, TRANSPARENT) ;
	 //  

  //      old = SelectObject (hdc, logfont_song[0]); 

		//CHAR buffer[256];
		//for(int i=0;i<12;i++)
		//{
		//	SelectObject (hdc, logfont_song[i]); 
		//	sprintf(buffer,"宋体请稍等8秒后重新输入%d",(4+i)*2);
		//	TextOut (hdc, 10 , 100+i*40, buffer, lstrlen (buffer)) ;
		//}

		//SelectObject (hdc, logfont_yahei);
		//for(int i=0;i<12;i++)
		//{
		//	SelectObject (hdc, logfont_yahei[i]); 
		//	sprintf(buffer,"雅黑请稍等8秒后重新输入%d",int((4+i)*2*1.4));
		//	TextOut (hdc, 400 , 100+i*40, buffer, lstrlen (buffer)) ;
		//}
		//SelectObject (hdc, old);

		//EndPaint (m_hwndMain, &ps) ;
	break;
	//case WM_SIZE:	
	//	RECT rcClient;
	//    GetClientRect(m_hwndMain, &rcClient);
	//    //SetWindows(&rcClient);
	//	break;
	case WM_LBUTTONDOWN:	
		
		ThreadOperator::Test();

            hMenu = CreateMenu();

            hSubMenu = CreatePopupMenu();
            AppendMenu(hSubMenu, MF_STRING, ID_FILE_EXIT, "E&xit");
            AppendMenu(hMenu, MF_STRING | MF_POPUP, (UINT)hSubMenu, "&File");

            hSubMenu = CreatePopupMenu();
            AppendMenu(hSubMenu, MF_STRING, ID_STUFF_GO, "&Go");
            AppendMenu(hMenu, MF_STRING | MF_POPUP, (UINT)hSubMenu, "&Stuff");

            SetMenu(m_hwndMain, hMenu);

            //hIcon = LoadImage(NULL, "menu_two.ico", IMAGE_ICON, 32, 32, LR_LOADFROMFILE);
            //if(hIcon)
            //    SendMessage(m_hwndMain, WM_SETICON, ICON_BIG, (LPARAM)hIcon);
            //else
            //    MessageBox(m_hwndMain, "Could not load large icon!", "Error", MB_OK | MB_ICONERROR);

            //hIconSm = LoadImage(NULL, "menu_two.ico", IMAGE_ICON, 16, 16, LR_LOADFROMFILE);
            //if(hIconSm)
            //    SendMessage(m_hwndMain, WM_SETICON, ICON_SMALL, (LPARAM)hIconSm);
            //else
            //    MessageBox(m_hwndMain, "Could not load small icon!", "Error", MB_OK | MB_ICONERROR);

		break;
	case WM_MOUSEMOVE:	
		break;
		// 菜单项被选中,或按钮被点击
	case WM_COMMAND:
		{
			switch (LOWORD(wParam))
			{
				// 在“帮助”菜单中选择“关于”
			case ID_HELP_ABOUT:
				{
					//DialogBox(
					//	m_hinst, (LPCTSTR)IDD_DIALOG_ABOUT, hwnd, (DLGPROC)About
					//	);
					return 0;
				}
		    case ID_FILE_EXIT:
                PostMessage(m_hwndButton, WM_CLOSE, 0, 0);
            break;
            case ID_STUFF_GO:

            break;

			default:
				break;
			}

			int t = HIWORD(wParam);
			//if (HIWORD(wParam) == /*LB_SELECTSTRING*/LBN_DBLCLK && m_hwndListBox == (HWND)lParam) 
			//{
			//	SetWindowText(m_hwndButton ,"Hi !"); 
			//}
			if ((HIWORD(wParam)&LBN_DBLCLK) && (*m_hwndListBox == (HWND)lParam)) 
			{
				SetWindowText(m_hwndButton ,"Hi !"); 
				int a = m_hwndListBox->GetSelectLine();
                int b = m_hwndListBox->GetSelectLine();
			}

			//控件通知消息,以命令消息的形式发送 
			if (HIWORD(wParam) == BN_CLICKED && m_hwndButton == (HWND)lParam) 
			{
				SetWindowText(m_hwndButton ,"Hi !"); 

				/*	ScrollWindow (hwnd, 0, -cyChar, &rect, &rect) ;
				hdc = GetDC (hwnd) ;
				SelectObject (hdc, GetStockObject (SYSTEM_FIXED_FONT)) ;

				TextOut(hdc, 0, 0,
					szBuffer,
					wsprintf (szBuffer, szFormat,
					message == WM_DRAWITEM ? TEXT ("WM_DRAWITEM") : 
					TEXT ("WM_COMMAND"),HIWORD (wParam), LOWORD (wParam),
					HIWORD (lParam), LOWORD (lParam))) ;

				ReleaseDC (hwnd, hdc) ;
				ValidateRect (hwnd, &rect) ;*/

				//TrackPopupMenu(hMenu,0,GET_X_LPARAM(lParam),GET_Y_LPARAM(lParam),0,hwnd,&rect);

			} 

			CheckBox 
			//if (HIWORD(wParam) == BN_CLICKED && hBtn2 == (HWND)lParam) 
			//{ 
			//	LRESULT r = SendMessage(hBtn2,BM_GETCHECK,0,0); 
			//	if(r==BST_CHECKED)//被选中 
			//	{ 
			//		MessageBox(NULL,L"CheckBox is CHECKED!",L"Hi!",MB_OK); 
			//	}
			//	else if(r==BST_UNCHECKED)//不被选中 
			//	{ 
			//		MessageBox(NULL,L"CheckBox is UNCHECKED!",L"Hi!",MB_OK);
			//	} 
			//	SetWindowText(hBtn ,L"Hi !"); 
			//} 

			//if (HIWORD(wParam) == STN_CLICKED && hStatic == (HWND)lParam) 
			//{
			//	MessageBox(NULL,_T("STATIC 通知消息"),L"hi",MB_CANCELTRYCONTINUE | MB_ICONEXCLAMATION); 
			//	SetWindowText((HWND)lParam ,L"Hi !"); 
			//}  


		/*	对这几个消息的理解要先了解一下Window消息的背景。   
  在Windows3.1里,控件会将mouse, keybord等等的消息通知它的父窗口, 使用的消息就只有WM_COMMAND, 事件种类和控件ID被包含在wParam中, 控件的句柄包含在lParam中。由于wParam和 lParam已经满了,当控件要向父窗口发送其它特殊消息同时附带很多信息的时

候就没有地方可以存放它们了。所以Windows3.1中定义了许多其它的消息种类,比如WM_VSCROLL, WM_CTLCOLOR等等,每种消息wParam,lParam中附带的信息是不同的。   
  当到了Win32后,控件的种类越来越多,当然不可以为每一个控件都定义一套消息,这样也不利于系统的扩充。所以在Win32中定义了唯一一个强大的消息WM_NOTIFY。当然WM_NOTIFY也遵守原来的消息规则,既只带参数wParam和lParam。唯一不同处在于,此时的lParam

中传送的是一个NMHDR指针。不同的控件可以按照规则对NMHDR进行扩充,因此WM_NOTIFY消息传送的信息量可以相当的大,这个可以看看MSDN中的相关说明,TreeControl中就有很多这种消息。   
    
  现在就可以知道为什么有ON_MESSAGE ,ON_COMMAND, , ON_NOTIFY了。   
  ON_MESSAGE是处理所有的Windows的消息的,因为所有的消息都以相同的格式传送,也就是ID, WPARAM, LPARAM.   
  ON_COMMAND是专门处理WM_COMMAND消息的,这样我们就不用自己解开WM_COMMAND中wParam和lParam中传送的控件ID, 事件种类…,所有的都在MFC内部解决了:),当然方便了。   
  ON_NOTIFY更是不用说了,看看他的处理函数,是不是把NMHDR解出来了。   
    
  这样一样就一目了然了,ON_COMMAND和ON_NOTIFY都可以用ON_MESSAGE来处理,只不过自己要多做很多事情。ON_COMMAND和ON_NOTIFY最好就不要互换了!   */

		}
	default:
		break;
	}
	return WAGuiDialog::WinProc(uMsg, wParam, lParam);

}

bool WAGuiTestDialog::OnChildWindowsNotify(PVOID pParam)
{
	LPNMHDR phdr = (LPNMHDR)pParam;
	if(m_hwndTreeView&&((*m_hwndTreeView) == phdr->hwndFrom))
	{
		switch (((LPNMHDR)pParam)->code)
		{
		// 如果是右键单击,则调用OnRclickTree函数弹出右键菜单
		case NM_RCLICK :
			OnRclickTree((LPNMHDR)pParam);
			//Browse(NULL); 
			//GetSpecialFolder(); 
			//GdiTest();
			//ListFileInRecycleBin(); 
		default:
			break;
		}
	}
	else if(phdr->hwndFrom == m_hwndButton)
	{
		int a = 0;
	}
	/*else if(m_hwndListBox&&((*m_hwndListBox) == phdr->hwndFrom))
	{
		int a = 0;
	}*/
	return TRUE;
}

/* 
* 判断是否在Tree View节点上单击
* 参数	pNMHDR,WM_NOTITY 消息的 lParam
* 返回值	是否单击了节点
*/
bool WAGuiTestDialog::OnRclickTree(NMHDR* pNMHDR)
{
	POINT point;
	TVHITTESTINFO thti;
	HTREEITEM htItem;

	GetCursorPos(&point);

	// 计算相对Client的鼠标位置,
	ScreenToClient(m_hwndTreeView->m_hwndMain,&point);
	thti.pt = point;
	thti.flags = TVHT_TORIGHT;
	// 获取被点击节点的句柄
	htItem =TreeView_HitTest(m_hwndTreeView->m_hwndMain,&thti);

	// 也可以根据节点属性的不同来弹出不同的右键菜单
	// TreeView_GetItem等函数可以用于获取TVITEM结构中的各个字段
	// 用户可以设置lParam字段来保存与节点相关的附加信息
	if(htItem!=NULL)
	{
		Browse(NULL);
		// DisplayContextMenu函数要求的鼠标位置是相对于屏幕的
		ClientToScreen(m_hwndTreeView->m_hwndMain,&point);
		// 选中用户右击的节点,否则Tree View中被选中的节点不会改变
		TreeView_SelectItem(m_hwndTreeView->m_hwndMain,htItem);
		// 调用DisplayContextMenu函数显示右键菜单
		DisplayContextMenu(m_hwndMain, point);
		return TRUE;
	}
	return FALSE;
}

WAGuiMgr::WAGuiMgr()
:m_hwndParent(NULL)
,m_hinst(NULL)
,m_hBitmap(NULL)
{}
void WAGuiMgr::Init(HWND hwnd,HINSTANCE inst)
{	
	//启动gdi+
	GdiplusStartupInput gdiplusStartupInput;
	ULONG_PTR           gdiplusToken;
	GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);

	m_hwndParent = hwnd;
	m_hinst = inst;
	// 保证通用控件动态链接库已经加载
	InitCommonControls();
    WAGuiDialog::Init();
	m_dialogs[DT_TEST] = new WAGuiTestDialog();
	m_dialogs[DT_TEST]->Create(m_hwndParent,"Test");
	
	WAGuiTopAnim::Init();
	m_topAnim.Create(0);

	//UNREFERENCED_PARAMETER(lpCmdLine);

	TestScreenCapture();

	CHAR szCurrentPath[MAX_PATH];
	GetCurrentDirectory(MAX_PATH,szCurrentPath);
	ListAllFileInDrectory(szCurrentPath);


	//关闭gdiplus的环境
	//GdiplusShutdown(gdiplusToken);
}

HBITMAP WAGuiMgr::TestScreenCapture()
{
	RECT rectShow;
	HWND hwndCap = FindWindow(NULL,"Windows 任务管理器");
	// 获取窗口的RECT,可自行修改,获取屏幕中的任意区域
	if(!GetWindowRect(hwndCap,&rectShow))
	{
		//MessageBox(NULL,"Can not find window to capture", "erroe",MB_OK);
		//return 0;
	}
	
	if(m_hBitmap)
		DeleteObject(m_hBitmap);

	// 截取屏幕,可根据需要设置不同的参数,这里只演示截取特定窗口。
    m_hBitmap = ScreenCapture("taskmgr.bmp" ,32, 0);//&rectShow);
	return m_hBitmap;
}

/* 功能 截取指定区域的屏幕,并保存为文件
*  参数	LPSTR filename 保存位图文件的文件路径,如果为NULL,则不保存
*		WORD BitCount Bit深度,用于表示一个像素点所使用的数据长度
*		LPRECT lpRect 所需截取的屏幕区域,如果为NULL,则获取全屏幕
*/
HBITMAP WAGuiMgr::ScreenCapture(LPSTR filename ,WORD BitCount,LPRECT lpRect)
{
	HBITMAP hBitmap;
	// 显示器屏幕DC
	HDC hScreenDC = CreateDC("DISPLAY", NULL, NULL, NULL);
	HDC hmemDC = CreateCompatibleDC(hScreenDC);
	// 显示器屏幕的宽和高
	int ScreenWidth = GetDeviceCaps(hScreenDC, HORZRES);
	int ScreenHeight = GetDeviceCaps(hScreenDC, VERTRES);
	// 旧的BITMAP,用于与所需截取的位置交换
	HBITMAP hOldBM;
	// 保存位图数据
	PVOID lpvpxldata;
	// 截屏获取的长宽及起点
	INT ixStart;
	INT iyStart;
	INT iX;
	INT iY;
	// 位图数据大小
	DWORD dwBitmapArraySize;
	// 几个大小
	DWORD nBitsOffset;
	DWORD lImageSize ;
	DWORD lFileSize ;
	// 位图信息头
	BITMAPINFO bmInfo;
	// 位图文件头
	BITMAPFILEHEADER bmFileHeader;
	// 写文件用
	HANDLE hbmfile;
	DWORD dwWritten;

	// 如果LPRECT 为NULL 截取整个屏幕
	if(lpRect == NULL)
	{
		ixStart = iyStart = 0;
		iX = ScreenWidth;
		iY =ScreenHeight;
	}
	else
	{
		ixStart = lpRect->left;
		iyStart = lpRect->top;
		iX = lpRect->right - lpRect->left;
		iY = lpRect->bottom - lpRect->top;
	}
	// 创建BTIMAP
	hBitmap = CreateCompatibleBitmap(hScreenDC, iX, iY);
	// 将BITMAP选择入内存DC。
	hOldBM = (HBITMAP)SelectObject(hmemDC, hBitmap);
	// BitBlt屏幕DC到内存DC,根据所需截取的获取设置参数
	BitBlt(hmemDC, 0, 0, iX, iY, hScreenDC, ixStart, iyStart, SRCCOPY);
	// 将旧的BITMAP对象选择回内存DC,返回值为被替换的对象,既所截取的位图
	hBitmap = (HBITMAP)SelectObject(hmemDC, hOldBM);
	if(filename == NULL)
	{
		DeleteDC( hScreenDC);
		DeleteDC(hmemDC);
		return hBitmap;
	}
	// 为位图数据申请内存空间
	dwBitmapArraySize = ((((iX*32) + 31) & ~31)>> 3)* iY;
	lpvpxldata = HeapAlloc(GetProcessHeap(),HEAP_NO_SERIALIZE,dwBitmapArraySize);
	ZeroMemory(lpvpxldata,dwBitmapArraySize);

	// 添充 BITMAPINFO 结构
	ZeroMemory(&bmInfo,sizeof(BITMAPINFO));
	bmInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
	bmInfo.bmiHeader.biWidth = iX;
	bmInfo.bmiHeader.biHeight = iY;
	bmInfo.bmiHeader.biPlanes = 1;
	bmInfo.bmiHeader.biBitCount = BitCount;
	bmInfo.bmiHeader.biCompression = BI_RGB;

	// 添充 BITMAPFILEHEADER 结构
	ZeroMemory(&bmFileHeader,sizeof(BITMAPFILEHEADER));
	nBitsOffset = sizeof(BITMAPFILEHEADER) + bmInfo.bmiHeader.biSize;
	lImageSize =
		((((bmInfo.bmiHeader.biWidth * bmInfo.bmiHeader.biBitCount) + 31) & ~31)>> 3)
		* bmInfo.bmiHeader.biHeight;
	lFileSize = nBitsOffset + lImageSize;
	bmFileHeader.bfType = 'B'+('M'<<8);
	bmFileHeader.bfSize = lFileSize;
	bmFileHeader.bfOffBits = nBitsOffset;

	// 获取DIB用于写入到文件
	GetDIBits(hmemDC, hBitmap, 0, bmInfo.bmiHeader.biHeight,
		lpvpxldata, &bmInfo, DIB_RGB_COLORS);
	// 写文件
	hbmfile = CreateFile(filename,
		GENERIC_WRITE,
		FILE_SHARE_WRITE,
		NULL,
		CREATE_ALWAYS,
		FILE_ATTRIBUTE_NORMAL,
		NULL);

	if(hbmfile == INVALID_HANDLE_VALUE)
	{
		MessageBox(NULL,"create file error","error",MB_OK);
	}

	WriteFile(hbmfile,&bmFileHeader,sizeof(BITMAPFILEHEADER),&dwWritten,NULL);
	WriteFile(hbmfile,&bmInfo,sizeof(BITMAPINFO),&dwWritten,NULL);
	WriteFile(hbmfile,lpvpxldata,lImageSize,&dwWritten,NULL);
	CloseHandle(hbmfile);

	// 释放内存,清除不同的DC。
	// 这里没有删除BITMAP对象,需在显示完成后删除
	HeapFree(GetProcessHeap(),HEAP_NO_SERIALIZE,lpvpxldata);
	ReleaseDC(0, hScreenDC);
	DeleteDC(hmemDC);	
	return hBitmap;
}

DWORD WAGuiMgr::ListAllFileInDrectory(LPSTR szPath)
{
//记录所有的文件和目录数
DWORD dwTotalFileNum = 0;
	CHAR szFilePath[MAX_PATH];

	WIN32_FIND_DATA FindFileData;
	HANDLE hListFile;
	CHAR szFullPath[MAX_PATH];

	//构造代表子目录和文件夹路径的字符串,使用通配符“*”
	lstrcpy(szFilePath, szPath);
	lstrcat(szFilePath, "\\*");
	//查找第一个文件/目录,获得查找句柄
	hListFile = FindFirstFile(szFilePath,&FindFileData);

	if(hListFile==INVALID_HANDLE_VALUE)
	{
		printf("错误:%d",GetLastError());
		return 1;
	}
	else
	{		
		do
		{
			//	过滤“.”和“..”,不需要遍历
			if(lstrcmp(FindFileData.cFileName,TEXT("."))==0||
				lstrcmp(FindFileData.cFileName,TEXT(".."))==0)
			{
				continue;
			}
			//构造成全路径
			wsprintf(szFullPath,"%s\\%s",
				szPath,FindFileData.cFileName);
			dwTotalFileNum++;
			//打印
			printf("\n%d\t%s\t",dwTotalFileNum,szFullPath);

			//如果是目录,则递归调用,列举下级目录
			if(FindFileData.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)
			{
				printf("<DIR>");
				ListAllFileInDrectory(szFullPath);
			}			
		}
		while(FindNextFile(hListFile, &FindFileData));
	}
	//FindClose();
	return 0;
}

WAGuiMgr G_GuiMgr;

========


版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/bcbobo21cn/article/details/52217745

智能推荐

音频分离Spleeter的安装_2stems.tar.gz-程序员宅基地

文章浏览阅读3.5k次,点赞5次,收藏13次。音频分离Spleeter的安装1.环境依赖及建立(需要已安装anaconda)1.0 项目源地址(github地址)1.1 创建虚拟环境1.2 激活虚拟环境1.3 conda 安装spleeter1.4 下载一个示例音乐1.5 将该音乐分离为两部分1.5.1 报错:No module named numba.decorators1.5.2 解决方案:1.6 下载分类模型1.6.1报错ValueError:Can't load save_path when it is None.1.6.2 解决方案:1.6._2stems.tar.gz

让你的软件飞起来:RGB转为YUV-程序员宅基地

文章浏览阅读64次。朋友曾经给我推荐了一个有关代码优化的pdf文档《让你的软件飞起来》,看完之后,感受颇深。为了推广其,同时也为了自己加深印象,故将其总结为word文档。下面就是其的详细内容总结,希望能于己于人都有所帮助。速度取决于算法同样的事情,方法不一样,效果也不一样。比如,汽车引擎,可以让你的速度超越马车,却无法超越音速;涡轮引擎,可以轻松超越音障,却无法飞出地球;如果有火箭发动机,就可以到达火..._bao.yuv

PX4装机教程(五)无人船(车)_在px4固体中如何设置差速船-程序员宅基地

文章浏览阅读2.5k次,点赞3次,收藏33次。文章目录前言一、载具设置二、电机接线三、PWM输出设置四、航点设置前言一个人可以走的更快,一群人才能走的更远,交流学习加qq:2096723956更多保姆级PX4+ROS学习视频:https://b23.tv/ZeUDKqy分享知识,传递正能量,如有疏漏或不当之处,恳请指出.PX4固件版本:1.10.0硬件:淘宝竞速船或者打窝船实验录屏https://www.bilibili.com/video/BV1wA411c7p3?spm_id_from=333.999.0.0一、载具设置单电机_在px4固体中如何设置差速船

一键批量查询快递单号,一键批量查询,共享备份物流,快递物流尽在掌控_批量快递查询-程序员宅基地

文章浏览阅读370次。每天都有大量的快递单号需要查询,如果一个个手动查询,不仅费时费力,还容易出错。为了解决这个问题,我们教您如何批量查询快递单号,并将快递物流信息进行备份并共享,实现高效管理。弹出一个对话框,文件名和保存类型不变,直接点“保存”,会提示备份成功,那么这个数据库就备份在电脑上了,也可以用第三方工具发送到其他电脑上。第四步,查询速度很快,我们就可以在主页面看到该批单号的运件信息了,比如:发出时间,状态,最后更新的物流时间,等等。第二步,在弹出来的文件框里,将需要查询的德邦快递单号都一一导入,并点击保存。_批量快递查询

敏捷开发(scrum)简介-程序员宅基地

文章浏览阅读7.7k次,点赞6次,收藏61次。敏捷开发(scrum)是一种软件开发的流程,强调快速反应、快速迭代、价值驱动。Scrum的英文意思是橄榄球运动的一个专业术语,表示“争球”的动作;运用该流程,你就能看到你团队高效的工作。一、四大价值观(特点)敏捷开发的特点就是下面4句话:「个体与交互」胜过「过程与工具」「可以工作的软件」胜过「面面俱到的文挡」「客户协作」胜过「合同谈判」「响应变化」胜过「遵循计划」说明:(1)敏捷开发(scrum)适用于竞争激烈,快速变化的市场。 敏捷的客户协作观念,快速迭代能帮助团队以最小成本,最快速_敏捷开发

string.h头文件和strings.h的区别-程序员宅基地

文章浏览阅读3.5k次。首先我们看一下man string 里面的内容:可见,strings 头文件中包含了部分函数,没有在 string.h 中出现的。上图的环境是 macOS Sierra 版本号为:10.12.6包括; index, rindex, strcasecmp, strncasecmp 这四个函数。为了一探这个头文件是不是只有macos 这种 Unix-like 系统中才出现。我在Linu..._strings.h

随便推点

linux CentOS 7下载步骤_centos7下载-程序员宅基地

文章浏览阅读4.8k次。linux CentOS 7下载步骤_centos7下载

Qt 22 布局管理器1 - QLayout,QBoxLayout,布局管理器的相互嵌套_qt layout可以嵌套layout吗-程序员宅基地

文章浏览阅读464次。布局管理器提供相关的类对界面组件进行布局管理能够自动排布窗口中的界面组件窗口变化后自动更新界面组件的大小QLayoutQLayout 是Qt 中布局管理器的抽象基类通过继承QLayout实现了功能各异且互补的布局管理器Qt中可以根据需要自定义布局管理器布局管理器不是界面部件,而是界面部件的定位策略QBoxLayout 布局管理器以水平或者垂直的方式管理界面组件水平:QHBoxLayout 水平布局管理器垂直:QVBoxLayout 垂直布局管理器sizePolicy:QSize_qt layout可以嵌套layout吗

error MSB6006 rc exe 已退出,代码为 5_vs2010报警 error msb6006: “rc.exe”已退出,代码为 5。-程序员宅基地

文章浏览阅读2.6k次。error MSB6006 rc exe 已退出,代码为 5_vs2010报警 error msb6006: “rc.exe”已退出,代码为 5。

如何用NAS打造私有协同办公系统?-程序员宅基地

文章浏览阅读6.2k次。对于人数不多的小型初创企业、工作室、SOHO人群来说,能够拥有自有的协同办公系统无疑是提高工作效率的好方法,同时将文件放在自己的服务器中,显然会更加安心,不用担心重要内容的泄露问题。因此,大家有没有这样想过,自己动手搭一套私有的、云端化的协同办公系统,搞定文件异地同步的同时,实现云端化的办公软件,并提升数据安全性。理想虽好,不过要亲手搞定这样的协同办公系统一定很困难吧?如果你真这样

假设你们的社团要精选社长,有两名候选人分别是A和B,社团每名同学必须并且只能投一票,最终的票多的人为社长。-程序员宅基地

文章浏览阅读33次。输出描述:一行,一个字符,A或B或E,输出A表示A得票数多,输出B表示B得票数多,输出E表示二人得票数相等。输入描述:一行,字符序列,包含A或B,输入以字符0结束。

BeanFactory和ApplicationContext有什么区别?_beanfactory和applicationcontext是干什么的-程序员宅基地

文章浏览阅读2.2k次,点赞2次,收藏2次。BeanFactory和ApplicationContext有什么区别? BeanFactory和ApplicationContext是Spring的两大核心接口,都可以当做Spring的容器。其中ApplicationContext是BeanFactory的子接口。(1)BeanFactory:是Spring里面最底层的接口,包含了各种Bean的定义,读取bean配置文档,管理..._beanfactory和applicationcontext是干什么的

推荐文章

热门文章

相关标签