window2000 DDK mirror驱动实现截屏Demo的简单研究

window2000 DDK mirror驱动实现截屏Demo的简单研究
window2000 DDK mirror驱动实现截屏Demo的简单研究


1、window DDK mirror的安装简单步骤:
下载ddk安装包路径请参考我之前的一篇文章。下载安装window 2000 DDK包后,便可以开始编译mirror的demo程序。安装的时候记得选上sample,这样才会有src的源码。安装ddk驱动之后,会安装到以下路径:C:/Program Files/NTDDK,在C:/Program Files/NTDDK/src/video/displays/mirror/dll目录下编译mirror.dll,在C:/Program Files/NTDDK/src/video/miniport/mirror目录下编译mirror.sys,编译时记得是用NTDDK自带的build命令(通过开始-》程序菜单来打开)。编译完这两个玩意之后,参考C:/Program Files/NTDDK/src/video/displays/mirror/app/readme.txt的内容来拷贝它们。ok,编译结束。然后通过手动安装的方式来安装这个驱动(通过控制面板,选择编译好的mirror.dll/mirror.sys)。非window 2000 DDK的编译安装步骤可能有所不同。

以上搞定了mirror驱动的编译和安装,成功安装之后,会在系统硬件设备管理的显示卡处看到多了一个Mirror Driver之类的设备,这就说明安装成功了。


2、mirror的Demo:
成功安装mirror之后,在这个目录下是可以编译一个demo程序的:C:/Program Files/NTDDK/src/video/displays/mirror/app,编译后的程序是C:/Program Files/NTDDK/src/video/displays/mirror/app/objchk/i386/ddmlapp.exe,但是根本没有起到demo的作用,运行之后只显示加载mirror驱动和注册表相关信息,根本没有意义。

所以,来看源代码吧。仔细分析了一下源代码(main.cxx),它的主要流程是:从系统中枚举获取mirror设备,然后修改注册表,把这个值Attach.ToDesktop设成1,即可与系统的屏幕绑定。接下来就是普通的GDI函数调用,通过位图来截取屏幕,因此需要对GDI函数有所了解才行。有所区别的地方是这里是用了mirror的设备,因此可以获取良好的性能(速度快,不会闪屏等):
HDC hdc = CreateDC("DISPLAY", deviceName, NULL, NULL);

这个main.cxx代码中注释了CreateMyWindow("Mirror Sample");这个内容,其实打开注释也没有效果。所以我认为这个sample如果不修改,是根本不可能看到截屏的效果。


3、为了实现mirror这个效果,我对源代码进行了部分修改,并且移到VC6++里面去了,只需要移main.cxx这个文件。我创建了一个Dialog的程序,把main.cxx和新增的main.h加到这个项目中,需要注意要加载include的路径:C:/Program Files/NTDDK/inc,以及动态库的路径:C:/Program Files/NTDDK/libchk/i386/,同时对main.cxx进行了修改,源代码附在后面。在Dialog上加一个button,去调用MirrorApp(0, NULL)就可以看到效果了。需要特别说明的是,这个仅仅是测试mirror的效果,未对程序进行任何合理性的优化,因此如果要用于项目上,需要自行优化。


4、我之前的文章还提到dfmirage这个驱动,其实它就是实现了一个类似mirror的驱动,我在下载安装dfmirage这个驱动之后,把main.cxx代码中与mirror有关的内容修改成dfmirage,效果是一样的。当然它可能做了一些优化处理,我没再仔细研究下去。


5、修改之后的main.cxx代码:
1)main.h
#ifndef _MIRROR_APP_H_
#define _MIRROR_APP_H_
void MirrorApp(int argc, char *agrv[]);
#endif //_MIRROR_APP_H_


2)main.cxx
//
// Generic Windows program template
//

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include "C://Program Files//NTDDK/inc//windows.h"


#define MM_MAX_NUMAXES          16
typedef struct tagDESIGNVECTOR
{
      DWORD  dvReserved;
      DWORD  dvNumAxes;
      LONG    dvValues[MM_MAX_NUMAXES];
} DESIGNVECTOR;

#include <winddi.h>

#include <tchar.h>
#include <winbase.h>
#include <winreg.h>

CHAR* programName;          // program name
HINSTANCE appInstance;  // handle to the application instance

HBITMAP hbm;

LPSTR driverName = "Microsoft Mirror Driver";

LPSTR dispCode[7] = {
    "Change Successful",
    "Must Restart",
    "Bad Flags",
    "Bad Parameters",
    "Failed",
    "Bad Mode",
    "Not Updated"};

int    giIndex = 0;

LPSTR GetDispCode(INT code)
{
    switch (code) {
   
    case DISP_CHANGE_SUCCESSFUL: return dispCode[0];
   
    case DISP_CHANGE_RESTART: return dispCode[1];
   
    case DISP_CHANGE_BADFLAGS: return dispCode[2];
   
    case DISP_CHANGE_BADPARAM: return dispCode[3];
   
    case DISP_CHANGE_FAILED: return dispCode[4];
   
    case DISP_CHANGE_BADMODE: return dispCode[5];
   
    case DISP_CHANGE_NOTUPDATED: return dispCode[6];
   
    default:
          static char tmp[MAX_PATH];
          sprintf(&tmp[0],"Unknown code: %08x/n", code);
          return (LPTSTR)&tmp[0];
   
    }
   
    return NULL;    // can't happen
}

//
// Handle window repaint event
//

VOID
DoPaint(
      HWND hwnd
      )

{
      HDC hdc;
      PAINTSTRUCT ps;
     
      hdc = BeginPaint(hwnd, &ps);

      COLORREF red = 0x00FF0000;

      HBRUSH hbr = CreateSolidBrush(red);

      RECT r;
      r.left = ps.rcPaint.left;
      r.top = ps.rcPaint.top;
      r.right = ps.rcPaint.right;
      r.bottom = ps.rcPaint.bottom;

      //FillRect(hdc, &r, hbr);

      HBRUSH dbrush;
      dbrush = CreatePatternBrush(hbm);
      FillRect(hdc, &r, dbrush);

      EndPaint(hwnd, &ps);
}


//
// Window callback procedure
//

LRESULT CALLBACK
MyWindowProc(
      HWND      hwnd,
      UINT      uMsg,
      WPARAM  wParam,
      LPARAM  lParam
      )

{
      switch (uMsg)
      {
      case WM_PAINT:
            //MessageBox(NULL, "Repaint !!", "OK", MB_OK);
            printf("get WM_PAINT msg.../n");
              DoPaint(hwnd);
              break;

      case WM_DISPLAYCHANGE:
            {
              WORD cxScreen = LOWORD(lParam);
              WORD cyScreen = HIWORD(lParam);
              WPARAM format = wParam;
             
              // Add hook to re-initialize the mirror driver's surface
            MessageBox(NULL, "Change !!", "OK", MB_OK);

            }
           
            printf("get WM_DISPLAYCHANGE msg.../n");
            break;

      case WM_DESTROY:
            printf("get WM_DESTROY msg.../n");
              PostQuitMessage(0);
              break;

      default:
            printf("get WM_DEFAULT msg.../n");
              //DoPaint(hwnd);
              return DefWindowProc(hwnd, uMsg, wParam, lParam);
      }

      return 0;
}


//
// Create main application window
//

HWND
CreateMyWindow(
    /
void MirrorApp(int argc, char *argv[])
{
      //programName = *argv++;
      //argc--;
      appInstance = GetModuleHandle(NULL);

      //printf("program name=%s/n", programName);
     

      //
      // Create the main application window
      //
      /
           
            char lsFileName[100]={0};
            sprintf(lsFileName, "d://a%d.bmp", giIndex++);
            SaveBitmap(lsFileName, hbm);


              // delete the device context
              DeleteDC(hdc2);
              DeleteDC(hdc);
              //
             
              //printf("/n--------------create my window !!/n");
              //CreateMyWindow("Mirror Sample");
              // ^^^^ Use this to test catching window initializiation messages.
              //

              // Disable attachment to desktop so we aren't attached on
              // the next bootup.  Our test app is done!

            //printf("/nPress any key to continue.../n");
            //getchar();


              DWORD zero = 0;
              if (RegSetValueEx(hKeyDevice,
                                                  _T("Attach.ToDesktop"),
                                                  0,
                                                  REG_DWORD,
                                                  (unsigned char *)&zero,
                                                  4) != ERROR_SUCCESS)
              {
                    printf("Can't set Attach.ToDesktop to 0x0/n");
                    return;
              }

              RegCloseKey(hKeyProfileMirror);
              RegCloseKey(hKeyDevice);

              printf("Performed bit blit.  Finished. /n");
      }
      else
      {
              printf("Can't get display settings./n");
      }
     
    // printf("/nPress any key to continue.../n");
      //getchar();

      return;
}

 原文: http://blog.sina.com.cn/maxtech
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值