精华内容
下载资源
问答
  • 本文主要介绍如何通过DLL注入的方式来实现在指定的窗口控件上挂载自定义窗口。 何谓挂载? 和舰载机挂载导弹类似,将我们自己的窗口挂到原有程序的窗口之上,可以实现对原有窗口功能的覆盖和扩展。 结合本实例的...

    一. 挂载原理

    本文主要介绍如何通过DLL注入的方式来实现在指定的窗口控件上挂载自定义窗口。

    何谓挂载?
    和舰载机挂载导弹类似,将我们自己的窗口挂到原有程序的窗口之上,可以实现对原有窗口功能的覆盖和扩展。

    结合本实例的代码,挂载的实现原理大致如下:

    1. 通过远程线程的方式(其他方式也可以)将DLL注入到指定的进程(当然是被挂载窗口所属的进程)。
    2. DllMainDLL_PROCESS_ATTACH条件分支中创建一个新线程NewThread,后面的处理逻辑将放到NewThread中,防止DllMain阻塞。
    3. 在NewThread线程中查找被挂载的窗口(注意是窗口不是窗口上的控件)的句柄(查找方式:EnumWindows结合FindWindowEx实现,详见FindProcessWindow函数)。
    4. 使用SetWindowLong修改窗体的默认的消息处理过程(假设将窗口处理过程修改为我们DLL中的WndProc_Trampoline函数),然后向窗体发送一个自定义消息,这时WndProc_Trampoline函数就可以获取到该消息通知,我们在收到该消息通知后就可以开始我们的挂载逻辑了。之所以要通过发送一个自定义消息的方式来做,而不是直接在新线程NewThread中开始我们的挂载逻辑,是因为这样做可以保证我们的挂载逻辑(如创建窗口)是在主线程中进行的。
    5. 挂载逻辑主要包含:查找需要挂载控件的句柄、创建挂载窗口。创建挂载窗口的时候要设置WS_CHILD子窗口属性,并设置父窗体的WS_CLIPCHILDREN属性来裁剪子窗口,防止我们挂载的子窗口闪烁。
    6. WndProc_Trampoline函数的最后不要忘记调用之前老的消息处理过程,否则原窗口的消息将无法得到正确的响应。

    二. 实例代码

    2.1 DllInjecter工程

    DllInjecter.exe实现将DLL注入到指定的进程之中,是一个通用的DLL注入器。包含了对前面文章介绍的“使用远程线程的方式注入”和“使用钩子方式注入”这两种注入方式的实现。

    这里写图片描述

    2.2 Test工程

    Test.exe是一个模拟的被挂载程序,程序非常简单,只包含一个窗体和大按钮,不包含任何逻辑。本实例主要是将我们的窗口挂载到这个大按钮之上。
    这里写图片描述

    2.3 Troy工程

    Troy.dll被注入到Test.exe中的DLL文件(名称来源于“特洛伊木马”)。挂载的主要逻辑大都在该工程之中。

    我们可以在WndProc_Trampoline函数的WUM_CREATE_USER_WINDOW消息处理分支中分别调用CreateUserWindowCreateUserWindowByDuilib函数来创建挂载窗口:
    - CreateUserWindow使用原始的Windows API(CreateWindow)创建挂载窗口。
    - CreateUserWindowByDuilib使用duilib界面库来创建挂载窗口。

    LRESULT CALLBACK WndProc_Trampoline(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
        switch (message) {
        case WUM_CREATE_USER_WINDOW:
            CreateUserWindowByDuilib();
            break;
        }
    
        return CallWindowProc(g_oldProc, hwnd, message, wParam, lParam);
    }
    LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
        switch (message) {
        case WM_PAINT:
            RECT rect;
            GetClientRect(hwnd, &rect);
            DrawText(GetDC(hwnd), TEXT("test"), 4, &rect, DT_CENTER);
            break;
        }
    
        return  DefWindowProc(hwnd, message, wParam, lParam);
    }
    unsigned int __stdcall PluginProc(LPVOID pArg) {
        MessageBox(NULL, TEXT("我已经被注入啦"), TEXT("信息"), MB_OK | MB_ICONASTERISK);
    
        HWND hMainWindow = InjectHelper::FindProcessWindow(GetCurrentProcessId(), TEXT("#32770"), TEXT("Test"), TRUE);
    
        g_oldProc = (WNDPROC)SetWindowLong(hMainWindow, DWL_DLGPROC, (LONG)WndProc_Trampoline);
    
    
        ::PostMessage(hMainWindow, WUM_CREATE_USER_WINDOW, 0, 0);
    
        return 0;
    }
    BOOL APIENTRY DllMain(HMODULE hModule, DWORD  fdwReason, LPVOID lpReserved) {
        HANDLE hThread = NULL;
    
        switch(fdwReason) {
            case DLL_PROCESS_ATTACH:
            {
                g_hDllModule = hModule;
                // 使用注册表方式和CreateRemoteThread方式注入时,一般在此处创建线程
                //
    
                hThread = (HANDLE)_beginthreadex(NULL, 0, PluginProc, NULL, 0, NULL);
                if (hThread) {
                    CloseHandle(hThread); // 关闭句柄,防止句柄泄漏
                }
                break;
            }
            case DLL_THREAD_ATTACH:
            {
                break;
            }
            case DLL_THREAD_DETACH:
            {
                break;
            }
            case DLL_PROCESS_DETACH:
            {
                break;
            }
        }
        return TRUE;
    }

    下面是使用duilib创建的挂载窗口的效果如图:
    这里写图片描述


    实例完整代码见:https://gitee.com/china_jeffery/inject_sample
    选择x86平台编译,x64平台未配置

    展开全文
  • 1 打开Internet选项  2 下载未签名的ACTIVEX控件-设为启动
    1 打开Internet选项 
    

     

    2 下载未签名的ACTIVEX控件-设为启动

     

     

    展开全文
  • 一个小型的.NET库,由支持,可拦截Windows PS4 Remote Play上的控件。 该库可用于自动执行任何PS4游戏。 请参阅。 另外,请检出存储库,以获取在此库上构建的即用型软件。 安装 使用NuGet(推荐) Install-...
  • 05_DoubleEdit_Demo 拦截并处理Win32控件的消息。 第7章(\ Chapter07) 示例描述:本章介绍Windows系统和外壳编程的技巧。 01_TimerDemo 使用计时器。 02_RegDemo 访问系统注册表。 03_SuperPwd 用...
  •  在开发定制Windows表单控件时,提供我们自己的下拉框类型编辑器来操作控件的属性常常是非常方便的。定制的类型编辑器不仅可以提供更为丰富的设计时刻体验,而且可能成为用户是否喜欢你的控件的决定因素。
  • Windows消息拦截技术的应用 民航合肥空管中心 周毅   一、前 言 众所周知,Windows程式的运行是依靠发生的事件来驱动。换句话说,程式不断等待一个消息的发生,然后对这个消息的类型进行判断,再做适当的处理...
    
     

    Windows消息拦截技术的应用

    民航合肥空管中心 周毅

     

    一、前 言

    众所周知,Windows程式的运行是依靠发生的事件来驱动。换句话说,程式不断等待一个消息的发生,然后对这个消息的类型进行判断,再做适当的处理。处理完此次消息后又回到等待状态。从上面对Windows程式运行机制的分析不难发现,消息在用户与程式之间进行交流时起了一种中间“语言”的作用。在程式中接收和处理消息的主角是窗口,它通过消息泵接收消息,再通过一个窗口过程对消息进行相应的处理。

    消息拦截的实现是在窗口过程处理消息之前拦截到消息并做相关处理后再传送给原窗口过程。通常情况下,程序员可以在窗口过程中处理接收到的消息,这就要求窗口过程必须在开发程序时完成,但是在一些应用中常常需要获取和处理另外应用程序或其它单元模块中的消息,实现此类功能的技术也就本文要讨论的主题――消息拦截技术。

     

    二、理解Windows消息机制

    在深入探讨消息拦截技术实现原理之前,让我们先来温习一下Windows消息机制原理知识。

    1、  消息的产生

    消息作为程序与外界交流的“语言”,它的产生自然来自外界,但这里所说的外界,不只是简单的指程序之外或软件系统之外,而是泛指消息处理模块之外的模块、Windows系统、其它应用程序以及硬件等。通常根据消息产生的方式将其分为两大类,即硬件消息和软件消息。硬件消息,常指由硬件装置所产生的事件(如鼠标或键盘被按下),放在系统消息队列(System Queue)中,再由系统消息处理机构将消息发送给应用程序消息队列中。软件消息,常指由Windows系统或其它应用程序发送的信息,它直接放入应用程序消息队列(Application Queue)中,再由应用程序消息处理机构将消息传递给相应的窗口。

    2、  消息的组成

    一个消息由一个消息名称(UINT),和两个参数(WPARAM,LPARAM)。当用户进行了输入或是窗口的状态发生改变时系统都会发送消息到某一个窗口。例如当菜单转中之后会有WM_COMMAND消息发送,WPARAM的高字中(HIWORD(wParam))是命令的ID号,对菜单来讲就是菜单ID。当然用户也可以定义自己的消息名称,也可以利用自定义消息来发送通知和传送数据。

    3、  消息的接收者

    一个消息必须由一个窗口接收。在窗口过程(WNDPROC)中可以对消息进行分析,对应用程序要求处理的消息进行相应的处理工作,对于那么不需要应用程序处理的消息可简单的调用缺省处理。例如你希望对菜单选择进行处理那么你可以定义对WM_COMMAND进行处理的代码,如果希望在窗口中进行图形输出就必须对WM_PAINT进行处理。

    4、  消息的处理

    窗口接收到发送给自己的消息后,将消息结构作为参数调用窗口过程对消息进行相应的处理。可以将窗口过程看作消息处理代码的集合,窗口过程函数的原型为:

    long FAR PASCAL WndProc(HWND hWnd,WORD message,WORD wParam,LONG lParam);
       其中,hWnd为窗口句柄,message为消息名称,wParam,lParam为两个参数。

       在Windows中,应用程序不直接调用任何窗口函数,而是等待Windows调用窗口函数,请求完成任务或返回信息。为保证Windows调用这个窗口函数,这个函数必须先向Windows登记,然后在Windows实施相应操作时回调,所以窗口函数又称为回调函数。WndProc是一个主回调函数,Windows至少有一个回调函数。它是在应用程序进行窗口类注册时向Windows登记的。

     

    三、利用钩子(Hook)拦截消息

    1、 何为钩子(Hook)?

    钩子(Hook)机制允许应用程序截获处理window消息或特定事件。与DOS中断截获处理机制有类似之处。钩子是Windows消息处理机制的一个平台,应用程序可以在上面设置子程以监视指定窗口的某种消息,而且所监视的窗口可以是其他进程所创建的。当消息到达后,钩子可以在目标窗口处理函数之前处理它并且可以阻止消息的传递。每一个钩子都有一个与之相关联的指针列表,称之为钩子链表,该链表中的指针指向这个钩子的各个处理子程。钩子的种类很多,每种钩子可以拦截并处理相应种类的消息。当钩子所监视的消息出现时,Windows调用链表中的第一个钩子子程,第一个过程完成后将消息传递链表中的下一个钩子子程,直至链表中所有钩子子程都执行完成(注意:如果在其中有一个钩子在执行完成前不执行消息传递,其后面的钩子过程和原窗口过程都不会再接收到消息。)后将消息返回给窗口过程。

    2、 钩子子程函数

    钩子子程是一个应用程序定义的回调函数。用以监视系统或某一特定类型的事件,这些事件可以是与某一特定线程关联的,也可以是系统中所有线程的事件。其函数原型为:

     

    LRESULT CALLBACK HookProc  (  int nCode, WPARAM wParam, LPARAM lParam );

     

    其中,nCode参数是Hook代码,Hook子程使用这个参数来确定任务。这个参数的值依赖于Hook类型,每一种Hook都有自己的Hook代码特征字符集。 Windows系统提供了多种类型的钩子,每一种类型的Hook可以使应用程序能够监视不同类型的系统消息处理机制。

    wParam和lParam参数的值依赖于Hook代码,但是它们的典型值是包含了关于发送或者接收消息的信息。

    3、钩子的安装与卸载

    钩子的安装是通过SDK API SetWindowsHookEx()来实现的,它将钩子子程安装到系统钩子链表中。其函数原型

     

    HHOOK SetWindowsHookEx( int idHook,HOOKPROC lpfn,HINSTANCE hMod, DWORD dwThreadId );

     

    其中,idHook是指钩子的类型。表一中列出部分钩子的类型及其说明。

    (表一)

    类型

    说明

    WH_CALLWNDPROC

    系统在消息发送到接收窗口过程之前调用此子程

    WH_CALLWNDPROCRET Hooks

    在窗口过程处理完消息之后调用此子程

    WH_GETMESSAGE

    监视从GetMessage / PeekMessage函数返回的消息

    WH_KEYBOARD

    监视输入到消息队列中的键盘消息

    WH_MOUSE

    监视输入到消息队列中的鼠标消息

    限于篇幅,其它消息类型就不一一列出了。有关内容可参见MSDN。

     

    lpfn是指钩子子程的地址指针。如果dwThreadId参数为0 或是一个由别的进程创建的线程的标识,lpfn必 须指向DLL中的钩子子程。除此以外,lpfn可以指向当前进程的一段钩子子程代码。 

     hMod是指应用程序实例的句柄。标识包含lpfn所指的子程的DLL。如果dwThreadId 标识当前进程创建的一个线程,而且子程代码位于当前进程,hMod必须为NULL。 

    dwThreadId是指与安装的钩子子程相关联的线程的标识符,如果为0,钩子子程与所有的线程关联。

    函数成功则返回钩子的句柄,失败返回NULL。

     

    钩子在使用完之后需要用UnHookWindowsHookEx()卸载,否则会造成麻烦。卸载钩子比较简单,UnHookWindowsHookEx()只有一个参数。函数原型如下:

    UnHookWindowsHookEx  ( HHOOK hhk  )

    其中,参数hhk是SetWindowsHookEx()函数返回钩子句柄,所以设计程序时一定要保存好这个句柄,以便卸载时使用。函数成功返回TRUE,否则返回FALSE。

     

    4、系统钩子与线程钩子

    Windows系统根据钩子监视事件的范围将钩子分为系统钩子(全局钩子)和线程钩子(局部钩子)两种。由SetWindowsHookEx()函数的最后一个参数决定了此钩子是系统钩子还是线程钩子。线程勾子用于监视指定线程的事件消息。线程勾子一般在当前线程或者当前线程派生的线程内。 系统勾子监视系统中的所有线程的事件消息。因为系统勾子会影响系统中所有的应用程序,所以勾子函数必须放在独立的动态链接库(DLL) 中。系统自动将包含"钩子回调函数"的DLL映射到受钩子函数影响的所有进程的地址空间中,即将这个DLL注入了那些进程。

     

    5、  钩子的实现

    本文的实例实现拦截记事本(NotePad.exe)程序的WM_CHAR消息的功能。如读者想实现其它功能,可直接在钩子子程函数中加入代码。

    (1)、选择MFC AppWizard(DLL)创建项目NotePadhook并选择MFC Extension DLL(共享MFC拷贝)类型。

    (2)、创建NotePadHook.h文件,在其中建立钩子类: 

     class AFX_EXT_CLASS CNotePadHook:public CObject 

     { 

     public:

     CNotePadHook(); //钩子类的构造函数

     ~CNotePadHook(); //钩子类的析构函数

     BOOL StartHook(HWND hWnd);  //安装钩子函数 

     BOOL StopHook(); 卸载钩子函数

     }; 

    (3)、在NotePadHook.cpp中加入#include “NotePadHook.h”。

    (4)、在NotePadHook.cpp中加入共享数据段:

    #pragma data_seg("sharedata")  //共享数据段,段内的变量可被钩子所有实例共享。

    HHOOK glhHook=NULL;  //钩子句柄。

    HINSTANCE glhInstance=NULL;  //DLL实例句柄。

    #pragma data_seg() 

    (5)、仅定义一个数据段还不能达到共享数据的目的,还要告诉编译器该段的属性。要在.DEF文件中设置段的属性,打开.DEF文件加入如下代码:

    SETCTIONS  //好像要改为SECTIONS  ,否则编译有错误

    sharedata READ WRITE SHARED 

     

    另外一种方法:

    也可以在代码中直接设置: 
      #pragma data_seg("sharedata")  
    .......... 
      #pragma data_seg()  
      #pragma comment(linker,"/SECTION:sharedata,RWS") 

     

    (6)、在主文件NotePadHook.cpp的DllMain函数中加入保存DLL实例句柄:

    DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)

    {

          //如果使用lpReserved参数则删除下面这行 

          UNREFERENCED_PARAMETER(lpReserved);

     

          if (dwReason == DLL_PROCESS_ATTACH)

          {

                TRACE0("NOtePadHOOK.DLL Initializing!/n");

                 //扩展DLL仅初始化一次 

               if (!AfxInitExtensionModule(NotePadHookDLL, hInstance))

                     return 0;

                new CDynLinkLibrary(NotePadHookDLL);

    //把DLL加入动态MFC类库中 

                glhInstance = hInstance;

           //插入保存DLL实例句柄 

          }

          else if (dwReason == DLL_PROCESS_DETACH)

          {

                TRACE0("NotePadHOOK.DLL Terminating!/n");

               //终止这个链接库前调用它 

                AfxTermExtensionModule(NotePadHookDLL);

          }

          return 1;  

    }

    (7)、类CNotePadHook的成员函数的具体实现:

    CNotePadHook::CNotePadHook(){}

    CNotePadHook::~CNotePadHook(){ StopHook(); }

    BOOL CNotePadHook::StartHook(HWND hWnd) //安装钩子。

    {

      BOOL bResult=FALSE;

    glhHook=SetWindowsHookEx(WH_CALLWNDPROC,NotePadProc,glhInstance,0);

      if(glhHook!=NULL) bResult=TRUE;

    return bResult;

    }

    CNotePadHook::StopHook()

    {

       BOOL bResult = FALSE;

       if(glhHook){

          bResult=UnhookWindowsHookEx(glhHook);

       if(bResult)  glhHook=NULL;

       return bResult;

    }

    (8)、钩子子程的实现:

    LRESULT WINAPI NotePadProc(int nCode,WPARAM wparam,LPARAM lparam) 

    {

      PCWPSTRUCT pcs = NULL;

    pcs = (PCWPSTRUCT)lParam;

          if( pcs && pcs->hwnd!=NULL )

          {

                 TCHAR szClass[256];

                 GetClassName(pcs->hwnd ,szClass,255);//获得拦截的窗口类名。

                 if( strcmp(szClass,"Notepad")==0)

                 {

                    if( pcs->message == WM_CHAR )

                      {

                         AfxMessageBox("HOOK NOTEPAD WM_CHAR OK!!!");

                      }

                  }

    }

        return CallNextHookEx(glhHook,nCode,wParam,lParam);//继续传递消息。

    }

     

    (9)、编译项目生成NotePadHook.dll。

     虽然已经完成了钩子类,但还不能实现钩子功能。我们必须写一个程序来启动钩子,将钩子DLL注入其它程序的内存空间并将钩子加入到系统钩子链表中。由于限于篇幅,在本文就不具体讲述钩子启动程序的实例,只将编写启动程序应注意的事项说明如下:

    (1)、将NotePadHook项目中Debug/NotePadHook.lib加入到项目设置链接标签中。

    (2)、将NotePadHook项目中NotePadHook.h文件include到stdafx.h。

    (3)、首先需要创建一个CNotePadHook类实例,启动钩子时调用类成员StartHook(),卸载钩子时调用类成员StopHook()。

     

    四、利用窗口子类化(SubClass)拦截消息

    前面已提及,每个窗口都有一个在它的窗口类中定义的窗口过程。该窗口过程处理每个发送到窗口的消息。如果想自己编写窗口过程,修改它的行为是没有问题的。但是,如果该窗口过程属于别人,则将没有源代码进行修改。例如,应用程序中的每个按钮,都是由系统提供的BUTTON窗口创建的,它有完全属于自己的窗口过程。如果想改变该窗口的外观,则不能通过改变它的WM_PAINT处理函数来实现,因为它是不可得的。那么,怎样能改变这些按钮的外观,而无需重新编写原来的控件呢?只要用自己的窗口过程的地址,替换窗口对象的初始窗口过程的地址即可。这种技术也是本节讨论的主题 – 窗口子类化技术。

      1、窗口子类化原理

    应用程序在创建一个新窗口之前要向Windows系统注册这个窗口的类,首先要填写一个WNDCLASS结构,其中的结构参数lpfnWndProc就是该类窗口函数的地址,接着调用RegisterClass()函数向Windows系统申请注册这个窗口类。这时Windows会为其分配一块内存来存放该类的全部信息,这个内存块称为窗口类内存块。

    窗口子类化技术实际上就是改变窗口内存块中的有关参数。由于这种修改只涉及到一个窗口的窗口内存块,因此它不会影响到属于同一窗口类的其它窗口的功能和表现。窗口子类化中最常见的是修改窗口内存块中的窗口函数地址(lpfnWndProc),使其指向一个新的窗口函数,从而改变原窗口函数的处理方法,以达到修改其窗口过程的目的。

    2、窗口子类化的实现

    窗口子类化实现的核心是改变窗口过程的地址,可以通过SDK API提供的几个函数来实现。具体步骤如下:

    a.编写子类化窗口过程函数。该函数必须为标准的窗口过程函数格式即: 

      LRESULT CALLBACK SubClassWndProc ( HWND , UINT , WPARAM , LPARAM ) ; 

        此函数的参数意义与前面讲述的窗口过程函数参数类似。

    b.调用GetWindowLong ( hWnd , GWL_WNDPROC ) 函数获得原窗口函数的地址并保存起来;其中参数hWnd为待子类化窗口句柄。

    C.调用SetWIndowLong ( hWnd , GWL_WNDPROC , SubClassWndProc ) 把窗口函数设置成子类化窗口函数,完成窗口子类化。 

     

    为了减少子类化过程中繁琐的工作,MFC中提供了对子类化的支持,它简化了子类化过程,利用CWnd类SubClassWindows()函数来实现子类化。为了让读者对子类化过程有一个直观的认识,下面将利用MFC实现对一个编辑(Edit)控件的子类化。

    (1)、创建一个从MFC控件类CEdit派生的新控件类CSubEdit。

    (2)、添加CSubEdit::PreTranslateMessage(MSG* pMsg)

    BOOL CSubEdit::PreTranslateMessage(MSG* pMsg)

    {

       if( pMsg->message==WM_KEYDOWN&&pMsg->wParam==VK_RETURN)

       {

      //当在Edit控件上按下回车键后…

     …..

    //限于篇幅处理内容略。

    return TRUE;

    }

    CEdit::PreTranslateMessage(pMsg);

    }

    (3)、在包含此控件的对话框类头文件中控件变量类型从CEdit改为CSubEdit。

    (4)、在包含此控件的对话框类文件中对Edit控件进行子类化,代码如下:

     HWND HwND;

      GetDlgItem(IDC_SUB_EDIT,&hWnd);//其中IDC_SUB_EDIT是控件ID。

     m_subEdit.SubclassWindow(hWnd); //m_subEdit为控件变量名。

     

    五、小结

    本文讨论了实现消息拦截的两种方法,其中钩子技术用途广泛,不仅可以实现对同进程内消息的拦截,而且还可以实现对另外进程消息的拦截。而子类化技术主要用于实现对同一进程单元模块中的窗口消息的拦截。程序员可以根据实际应用需求选择其一来实现消息的挡截。

     

    http://blog.csdn.net/jiangxinyu/article/details/5276538

    展开全文
  • Windows SDK设置控件支持Tab键

    千次阅读 2013-08-29 10:38:41
    在使用windows api编程时,若是页面有很多编辑框EDIT,那么,能否支持Tab键将会很影响用户体验。。 我在使用codeblocks写Win32GUI工程时,建立了一个Frame Based的项目,然后进行编程,创建了一堆的Edit控件,代码...

    在使用windows api编程时,若是页面有很多编辑框EDIT,那么,能否支持Tab键将会很影响用户体验。。

    我在使用codeblocks写Win32GUI工程时,建立了一个Frame Based的项目,然后进行编程,创建了一堆的Edit控件,代码如下:

    Hwnd_EDIT_Set_IP=CreateWindow(TEXT("EDIT"),TEXT(""),WS_CHILD | WS_BORDER|WS_TABSTOP,290,45,
                                      90,20,hwnd,(HMENU)ID_Common,((LPCREATESTRUCT) lParam)->hInstance,NULL);
    Hwnd_EDIT_Set_DB=CreateWindow(TEXT("EDIT"),TEXT(""),WS_CHILD | WS_BORDER|WS_TABSTOP,290,75,
                                      90,20,hwnd,(HMENU)ID_Common,((LPCREATESTRUCT) lParam)->hInstance,NULL);
    Hwnd_EDIT_Set_User=CreateWindow(TEXT("EDIT"),TEXT(""),WS_CHILD | WS_BORDER|WS_TABSTOP,290,105,
                                        90,20,hwnd,(HMENU)ID_Common,((LPCREATESTRUCT) lParam)->hInstance,NULL);
    Hwnd_EDIT_Set_Pass=CreateWindow(TEXT("EDIT"),TEXT(""),WS_CHILD | WS_BORDER|WS_TABSTOP,290,135,
                                        90,20,hwnd,(HMENU)ID_Common,((LPCREATESTRUCT) lParam)->hInstance,NULL);
    Hwnd_EDIT_Set_Interval=CreateWindow(TEXT("EDIT"),TEXT(""),WS_CHILD | WS_BORDER|WS_TABSTOP,290,165,
                                            90,20,hwnd,(HMENU)ID_Common,((LPCREATESTRUCT) lParam)->hInstance,NULL);

    很明显,为了使控件支持Tab键,在用CreateWindow创建控件时,必须在窗体风格参数dwStyle上指定WS_TABSTOP风格。。。

    可是,一旦debug就发现,程序依然不响应Tab键。。。

    解决方案:

    虽然指定了WS_TABSTOP风格,但是,如果要程序响应Tab键,则必须要操作系统向程序发送Tab键指令啊。。。问题就处在这里了,对于FrameBased应用项目来说(DialogBased没有试过),正常情况下,你的Tab键消息被操作系统给拦截了,所以即使你指定了WS_TABSTOP风格,程序依然不会响应。

    为了解决这个问题,需要在WinMain函数中,窗口进入消息循环时添加一句代码,让操作系统不拦截消息。。。代码如下:

    while (GetMessage (&messages, NULL, 0, 0))
        {
            if(!IsDialogMessage(hwnd,&messages))//这一句是必要的,必须添加
            {
                /* Translate virtual-key messages into character messages */
                TranslateMessage(&messages);
                /* Send message to WindowProcedure */
                DispatchMessage(&messages);
            }
        }

    需要注意的是:上面这样进行操作后,会导致有些消息无法被传入消息处理函数,例如WM_KEYDOWN消息,将直接被操作系统拦截了,导致消息处理函数中关于按键消息的函数响应失败~正确的做法最好如下:

    while (GetMessage (&messages, NULL, 0, 0))
        {
            if(!IsDialogMessage(hwnd,&messages))
            {
                /* Translate virtual-key messages into character messages */
                TranslateMessage(&messages);
                /* Send message to WindowProcedure */
                DispatchMessage(&messages);
            }
            else
            {
                TranslateMessage(&messages);
                DispatchMessage(&messages);
            }
        }


    展开全文
  • 一、前 言 众所周知,Windows程式的运行是依靠发生的事件来驱动。换句话说,程式不断等待...消息拦截的实现是在窗口过程处理消息之前拦截到消息并做相关处理后再传送给原窗口过程。通常情况下,程序员可以在窗口过程
  • 拦截EDIT控件中的消息问题(上次提问过,我自己找了些资料,虽然拦截到消息,可得到的是空白字符) Delphi / Windows SDK/APIhttp://www.delphi2007.net/DelphiAPI/html/delphi_20061117131358209.html 接上次的...
  • VC控件拦截回车键

    2012-01-17 02:05:40
    VC控件拦截回车键 2010年07月19日  本文讲述了在指定的编辑框上能响应从键盘输入回车键的一种方法,对进程内消息的解析、动态获取指定资源ID等技术也作了简要描述。  一、引言  在通常的以CEditView为基类...
  • 在开发定制Windows表单控件时,提供我们自己的下拉框类型编辑器来操作控件的属性常常是非常方便的。定制的类型编辑器不仅可以提供更为丰富的设计时刻体验,而且可能成为用户是否喜欢你的控件的决定因素。 如果你...
  • Windows程序设计-子窗口控件

    千次阅读 2017-09-11 22:25:01
    按钮类别/*---------------------------------------- BTNLOOK.C -- Button Look Program (c) Charles Petzold, 1998 ----------------------------------------*/#include <windows.h>struct {
  • 的组件支持历来都是它的一大卖点,于是第三方软件开发商们纷纷开发出各种具有新功能性的可视控件 (也有少数非可视控件) 供 Visual Basic 程序员选用。这种特殊的 Visual Basic 开发形式创造了无数的第三方控件——...
  • 在开发定制windows表单控件时, 提供我们自己的下拉框类型编辑器来操作控件的属性经常是非常方便的。 定制的类型编辑器不只可以提供更为丰富的设计时辰体验, 而且可能成为用户是否喜欢你的控件的决议要素。 假设你...
  • 的组件支持历来都是它的一大卖点,于是第三方软件开发商们纷纷开发出各种具有新功能性的可视控件 (也有少数非可视控件) 供 Visual Basic 程序员选用。这种特殊的 Visual Basic 开发形式创造了无数的第三方控件——...
  •  其实本代码段最主要是以一种外挂的方式,拦截窗口上的控件事件(windows 消息)前提是控件本身并没有实现,比如代码中的 WM_LBUTTONDBLCLK 消息 button 并没有提供相应的事件封装 ( 按钮双击没有意义,请不要模仿...
  • WPF下取得控件或窗体的句柄 窗体: IntPtr hwnd = new WindowInteropHelper(this).Handle; 控件: IntPtr hwnd = ((HwndSource)...WPF提供了一个HwndSource可以使你更快的实现处理Windows消息。 ...
  • 一、前 言 众所周知,Windows程式的运行是依靠发生的事件来驱动。换句话说,程式不断等待一个消息的发生,然后对这个消息的类型进行...从上面对Windows程式运行机制的分析不难发现,消息在用户与程式之间进行交...
  • Windows SDK下ListBox控件的使用

    千次阅读 2013-08-22 21:01:29
    【这些消息可以在WindowProcedure函数中switch(message)中通过WM_COMMAND消息的case语句进行拦截,设置相应的响应函数】 ListBox可以产生的通知消息 LBN_ERRSPACE 内存分配失败 LBN_...
  • 取父窗口的窗口句柄:hwndParent = GetParent (hwnd) ;发送消息:SendMessage (hwndParent, message, wParam, ...当使用预定义的控件时,不必为其注册窗口类,窗口类已经存在于Windows中,并有一个预先定义的名字。

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 6,195
精华内容 2,478
关键字:

windows拦截的控件