Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1135954
  • 博文数量: 222
  • 博客积分: 5262
  • 博客等级: 大校
  • 技术积分: 3028
  • 用 户 组: 普通用户
  • 注册时间: 2009-11-22 19:10
文章分类

全部博文(222)

文章存档

2012年(2)

2011年(192)

2010年(28)

分类: WINDOWS

2011-01-26 12:43:47

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
#include
#include
#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

#include
#include
#include

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;
}

阅读(3848) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~