DirectX全屏游戏中弹出窗口(转)
一直有人问如何在DirectX全屏游戏中弹出窗口就象金山游侠一样.我答应过要给出原码,只是一直没有时间整理,不过现在总算是弄玩了.代码不长,大致作了些注释,但愿你能看懂:)
按照我的说明一步步作应该就能成功,但有时可能不行,为什么?我也不知道,或许是你哪一步做错了,或者是Delphi的问题?天知道,但大多数时候按照我给出的步骤,这些代码应该能实现我们的目标.
下面的代码经过了一定的测试,但并没有刻意设计保证程序兼容性和稳定性的代码,所以不能保证在所有的机器上正常运行.如果死机或者花屏了,那么很不幸它不适合你,在找些别人写的类似的代码吧(不过以前有人公开过类似的代码吗?如果有请mail给我:)
试一试吧,希望我们能把它完善起来.
{***************HOOK.DLL************
FileName:Hook.dpr(The KEY unit to pop up a window in DX apps)
Author: tTui or tt.t (As u like ;)
Feature:This unit contain the Demo codes for pop up an MODAL window in Apps which use exclusive directX fullscreen mode.
Description: 1.Uses KeyBoard hook to hook the hotkey.
2.Uses s0me tricks to get the *real* IDirectDraw pointer.
3.Call the *IDirectDraw.FilptoGDISurface* to make sure the poped up window could be seen.(See MSDN for the reason)
4.Uses GetMessage hook to hook the WM_TIMER,WM_SETFOCUS... messages.(Why?I don't want to tell u :) Find the reason by urself)
5.The HotKey is Left WIN + NumPad *
6.Mute codes needed, but havn't wrote yet.
7.Complied with Delphi 6. Tested under Win98&SE, Win ME, Win 2K,Win XP and Win 2003.NET with DirectX 8&9.
Known Bugs: 1.Cannot repaint the background when the poped up window moved.
2.May crash when try to pop up from some games and apps.
3.Cannot show the cursor in some games.
4.May minimize the main App, when try to pop up the window.
5.Many more...but unknown yet...
MY MAIL: ttui@163.com
BTW, if u want to pop up an MODALLESS window, u should write the codes all by urself.
*DO NOT* ask me for that.
***********************************}
library Hook;
uses
SysUtils,
Classes,
Windows,
Messages,
Dialogs,
DirectDraw, //*Modified* Jedi's DirectX header file for Delphi.
FormUnit in 'FormUnit.pas' {Form1}; //The unit contains the popup window.
{$R *.res}
type
PHookRec = ^THookRec;
THookRec = record
ParentWnd:HWND; //The main app's handle
FormWnd:HWND; //Handle of the popup window
Poped:Boolean; //A flag. eq True if the window poped
HH1:HHOOK; //Hook handle of the keyboard hook
HH2:HHOOK; //Hook handle of the GetMessage hook
end;
var
rHookRec: PHookRec = nil;
hMapObject: THandle = 0;
var
pDirectDrawCreate:function (lpGUID: PGUID;out lplpDD: IDirectDraw;pUnkOuter: IUnknown) : HResult; stdcall;
function WHGETMESSAGE(iCode:Integer;wParam: WPARAM;lParam: LPARAM):LRESULT; stdcall;
begin
result:=0;
if iCode<0 then
begin
CallNextHookEx(rHookRec^.HH2,iCode,wParam,lParam);
result:=0;
Exit;
end;
case PMSG(lParam)^.message of
WM_TIMER, //$113
WM_WINDOWPOSCHANGING, //$47
WM_SETCURSOR, //$20
WM_ACTIVATEAPP, //$1c
WM_SETFOCUS: //$7
begin //Some other messages should be processed here.
PMSG(lParam)^.message:=0;
end;
end;
end;
function HookProc(iCode:Integer;wParam: WPARAM;lParam: LPARAM):LRESULT; stdcall;
var
dh:dword;
FD:IDirectDraw;
pp:pointer;
a:dword;
sc:integer;
begin
result:=0;
if iCode<0 then
begin
CallNextHookEx(rHookRec^.HH1,iCode,wParam,lParam);
result:=0;
Exit;
end;
if ((lParam and $80000000)=0) and
(GetKeyState(VK_LWIN)<0) and (wParam=$6a) then //The HotKey is Left WIN + NumPad *
begin
rHookRec^.ParentWnd:=getforegroundwindow;
if not isWindow(rHookRec^.ParentWnd) then exit;
try
if not rHookRec^.Poped then
begin
dh:=GetModuleHandle('ddraw.dll'); //is a dx app??
if dh<>0 then
begin
dh:=dword(GetProcAddress(dh,'DirectDrawCreate'));
if dh<>0 then
begin
pDirectDrawCreate:=Pointer(dh);
if pDirectDrawCreate(nil,FD,nil)=0 then
begin
pp:=@fd;
a:=dword(pointer(dword(pp^)+8)^); //Now a is the pointer to the *REAL* IDirectDraw
asm //Call FliptoGDISurface
mov eax,a
push eax
mov eax,[eax]
call [eax+$28]
end;
FD:=nil;
end;
end;
end;
rHookRec^.HH2:=setwindowshookex(WH_GETMESSAGE,@WHGETMESSAGE,0,GetCurrentThreadID);
sc:=ShowCursor(true); //Show cursor
form1:=tform1.CreateParented(rHookRec^.ParentWnd); //Create the window that'll pop up
rHookRec^.Poped:=true; //set flag
rHookRec^.FormWnd:=form1.Handle;
form1.ShowModal; //Bingo!! The window pops up!!
form1.Free;
rHookRec^.Poped:=false; //set flag
UnhookWindowshookEx(rHookRec^.HH2);
if sc>=0 then
ShowCursor(true)
else
ShowCursor(false);
end;
finally
end;
result:=1;
end;
end;
function sethook:bool;export; //Call the func to set the keyboard hook
begin
result:=false;
if rHookRec^.HH1<>0 then exit;
rHookRec^.Poped:=False;
rHookRec^.HH1 := SetWindowsHookEx(WH_KEYBOARD,hookproc,HInstance,0);
Result := rHookRec^.HH1 <> 0;
end;
function endhook:bool;export; //Call the func to unhook the keyboard hook
begin
if rHookRec^.HH1 <> 0 then
begin
UnhookWindowshookEx(rHookRec^.HH1);
rHookRec^.HH1 := 0;
end;
Result := rHookRec^.HH1 = 0;
end;
procedure EntryPointProc(Reason: Integer); //Create and Close the file mapping to share data in different processes.
begin
case reason of
DLL_PROCESS_ATTACH:
begin
hMapObject := CreateFileMapping($FFFFFFFF, nil, PAGE_READWRITE, 0, SizeOf(THookRec), '_Popup_A_Wnd_DEMO_');
rHookRec := MapViewOfFile(hMapObject, FILE_MAP_ALL_ACCESS, 0, 0, SizeOf(THookRec));
end;
DLL_PROCESS_DETACH:
begin
try
UnMapViewOfFile(rHookRec);
CloseHandle(hMapObject);
except
end;
end;
end;
end;
Exports
SetHook,
EndHook;
begin
DllProc := @EntryPointProc;
EntryPointProc(DLL_PROCESS_ATTACH);
end.
//==================================================
{*************FormUnit.pas**********
FileName:FormUnit.pas
Author: tTui or tt.t (As u like ;)
Description: This unit contains the codes of the popup window.
MY MAIL: ttui@163.com
TIPS:The form's BoaderStyle property must be "bsDialog" or the popup window may not be seen.
***********************************}
unit FormUnit;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs;
type
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject); //u can add other VCL components.
private
{ Private declarations }
procedure WndProc(var Message: TMessage); override;
public
{ Public declarations }
end;
type
PHookRec = ^THookRec;
THookRec = record
ParentWnd:HWND;
FormWnd:HWND;
Poped:Boolean;
HH1:HHOOK;
HH2:HHOOK;
end;
var
Form1: TForm1;
TILC_Message:Cardinal; //Exit message
rHookRec: PHookRec = nil;
hMapObject: THandle = 0;
implementation
{$R *.dfm}
procedure TForm1.WndProc(var Message: TMessage);
begin
inherited WndProc(Message);
if Message.Msg=TILC_Message then
Close;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
TILC_Message:=RegisterWindowMessage(pchar('Poooop!!'));
hMapObject := CreateFileMapping($FFFFFFFF, nil, PAGE_READWRITE, 0, SizeOf(THookRec), '_Popup_A_Wnd_DEMO_');
rHookRec := MapViewOfFile(hMapObject, FILE_MAP_ALL_ACCESS, 0, 0, SizeOf(THookRec));
// the popup window cann't access its handle via its property "form.handle" or an exception'll rise.
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
try
UnMapViewOfFile(rHookRec);
CloseHandle(hMapObject);
except
end;
end;
end.
//========================================
{***************Test.pas************
FileName:Test.pas
Author: tTui or tt.t (As u like ;)
Description: This unit demostrates how to use HOOK.DLL.
File->New->Application
MY MAIL: ttui@163.com
***********************************}
unit Test;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
private
{ Private declarations }
public
{ Public declarations }
end;
function sethook:Bool;External 'Hook.DLL';
function endhook:Bool;External 'Hook.DLL';
var
Form1: TForm1;
TILC_Message:Cardinal;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
begin
if Button1.Caption='SetHook' then
begin
SetHook;
Button1.Caption:='EndHook';
end
else
begin
Button1.Caption:='SetHook';
EndHook;
end;
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
EndHook;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
TILC_Message:=RegisterWindowMessage(pchar('Poooop!!'));
end;
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
var
r:DWORD;
begin
r:=BSM_APPLICATIONS;
BroadcastSystemMessage(BSF_QUERY,@r,TILC_Message,0,0); //Broadcast the exit message when quit.
end;
end.
//===============================
Finally, we must modify the DirectDraw.pas to prevent to load the ddraw.dll when the application runs.
Find the initialization part at the end of DirectDraw.pas and add
"if false then" before "if not IsNTandDelphiRunning then".
DirectX全屏游戏中弹出窗口(转)的更多相关文章
- OBS录制全屏游戏的方法(超好录屏)
新版Windows设置 详见 https://github.com/obsproject/obs-studio/wiki/Laptop-Troubleshooting 新版的Windows 10: l ...
- MFC全屏显示和多窗口动态显示的一些技巧和方法
一.全屏 1.全屏窗口从dialogex继承,因为要处理一些东西 2.全屏代码,这样设置后尺寸不会出bug,只设置为最大值的话容易出bug //get current system resolutio ...
- nvidia 无显示选项怎么设置全屏游戏
转自:2楼 http://nbbbs.zol.com.cn/41/218_408871.html 网上搜的方法: 1.按键盘上那个windows键+R,输入regedit 2.然后就是下面的步骤了 ...
- JS只弹出一个居中弹出窗口
var newWindow;//定义一个窗口,有利于窗口间的通讯function makeNewWindow(url) { if (!newWindow || newWindow.closed) ...
- webdriver设置浏览器全屏及设置浏览器窗口为特定大小的方法
from selenium import webdriver driver = webdriver.Chrome() #全屏 driver.maximize_window() #具体大小 driver ...
- CEF中弹出窗口的处理
CEF开发如果不想在弹出窗口中打开网页,即想要在当前窗体加载目标Url, 就需要重写OnBeforePopup,它是属于CefLifeSpanHandler类中的. /*--cef(optional_ ...
- 在IE7+ 中弹出窗口并关闭本身窗口的脚本(备忘)
window.onload =function(){ window.open("http://www.126.com"); window.opener=null; window.o ...
- win7系统玩游戏不能全屏的解决办法
1.修改注册表中的显示器的参数设置 Win键+R键,打开运行窗口,输入regedit回车,这样就打开了注册表编辑器,然后,定位到以下位置: HKEY_LOCAL_MACHINE\SYSTEM\ ...
- QT中关于窗口全屏显示与退出全屏的实现
近期在学习QT时遇到了很多问题这也是其中一个,个人通过在各种书籍和网络上的查阅找到了一些关于这方面的答案,希望能给大家一些帮助. 首先,在QT中对于窗口显示常用的有这么几个方法可以调用: Qt全屏显示 ...
随机推荐
- 八、mini2440裸机程序之UART(2)UART0与PC串口通信【转】
转自:http://blog.csdn.net/shengnan_wu/article/details/8309417 版权声明:本文为博主原创文章,未经博主允许不得转载. 1.相关原理图 2.相关寄 ...
- poj1273
赤裸裸的最大流 #include <iostream> #include <cstdio> #include <cstdlib> #include <cstr ...
- TimedSupervisorTask
啊啊啊 UnsupportedOperationException Lists.emptyLIst() . add (String[] ) 这他妈的不行.. .2017/09/13 16:42:16. ...
- 在内部局域网内搭建HTTPs
在内部局域网内搭建HTTPs 配置环境 Windows版本:Windows Server 2008 R2 Standard Service Pack 1 系统类型: 64 位操作系统 内存 ...
- 2018-11-1 NOIP 模拟赛解题报告
T1 Domino 多米诺骨牌 题目大意 给你N个骨牌,上下各有一个数,要使上面一排的和为偶数,同时下面一排的和也为偶数,最多要翻转多少次?如果无法达成那么输出-1. 解法 水题秒切 根据数的奇偶性质 ...
- Taints和Tolerations联用,将pod部署到k8s的master节点
一般,k8s的master为了保持高性能,在这个主节点上只运行一些管理必须的POD. 如果我们限于资源,或是一些监控类的pod要部署到master节点呢? 昨天遇到这个问题,按网上通用的方法,未解决, ...
- dojo 加载自定义module的路径问题
因为最近想学学ArcGIS API for JavaScript ,翻了下ESRI的官网guide,发现其是基于dojo框架的,看了两页实在看不懂,于是先来熟悉下dojo框架.人蠢不能怪社会%> ...
- Git(二)使用git管理文件版本(TortoiseGit )
一.创建版本库 什么是版本库呢?版本库又名仓库,英文名repository,你可以简单理解成一个目录,这个目录里面的所有文件都可以被Git管理起来,每个文件的修改.删除,Git都能跟踪,以便任何时刻都 ...
- Webpack按需加载一切皆模块
前言 在学习 Webpack 之前,我们需要了解一个概念:模块. 何为模块? 如果你曾学过 Java , C# 之类的语言,一定会知道 Java 中的 import 或 C# 中的 using 吧? ...
- 【LOJ】#2082. 「JSOI2016」炸弹攻击 2
题解 想到n3发现思路有点卡住了 对于每个发射塔把激光塔和敌人按照极角排序,对于一个激光塔,和它转角不超过pi的激光塔中间夹的敌人总和就是答案 记录前缀和,用two-Points扫一下就行 代码 #i ...