下面这对对话在研究使用directdraw的游戏汉化时可能能用上。+ V9 Q$ C$ N% ?5 x' {$ h! k
$ g) M9 M4 D0 M
原文
( \' ^9 z; c5 U, {- z4 @http://www.qqgb.com/Program/VC/VCJQ/Program_177879.html 1 e) {( b6 X: u2 E2 E+ s
0 T o8 G X0 E% O( {! t4 Ddirectdraw主表面显示文字问题 前提:已经Hook了ddraw.dll的几个关键API(包括接口的虚函数表),成功获取到了主表面。
0 A! {7 p% ~& c1 h! T/ A1 X, m问题:向主表面的HDC TextOut后,文字是显示出来了,但都保持在屏幕的最顶层,其它窗口经过时也会显示文字。
! ?. {% {5 M( i S9 P, [: o( ]8 F为什么没有附在原窗口(用来显示主表面的)中呢? 第1个回答
! C; t% P! C! O h' x% Y) A% G# z居然还有这种事?HDC是ddraw窗口的DC吗?一个DC绘制的图形不是分离的对象,不可能被拆成两部分显示。后台表面也要同时hook绘制。 9 {* }* @! X/ U& ^% k' ]+ [1 @
--------------------------------------------------------------------------------
* e7 I; [( w+ `8 m# L8 K第2个回答
5 b& g& k! z' u$ R% Y% z+ q# @0 ZHDC 是主表面实例指针-> GetDC()的,不是窗口的HDC。后台表面GetDC()失败,应该不是真正的后台,它不是用Flip进行显示的,而是主表面用Blt绘制另外一个非主表面。 : e1 A3 Z! q7 I- ?- M
--------------------------------------------------------------------------------
( w3 M" {2 N) T3 `第3个回答
8 N" g+ i1 k+ ~9 ]窗口界面的DDraw程序肯定不可能使用Flip了。 / P1 M% a# Y& q, P9 n
主表面上绘制东西出界是常有的事情,首先要设置Clipper,而且在绘制的时候还要自己获取窗口坐标进行坐标变换,这样才能保证绘制在窗口上。 2 f" d2 C* F X A: Z
--------------------------------------------------------------------------------
3 @# P4 g, U% i# f第4个回答* K( V1 X! l" E) T
我是想在第3方的视频播放器中显示文字,已经Hook了DDraw.dll,得到了主表面实例指针lpddsPrimary,此时主表面已经设置过了Clipper,
$ Q) ?; R: A0 K" ~1 w) b7 c6 _6 N* [2 ?1 I我只是lpddsPrimary-> GetDC(),然后Textout,出现显示的文字和画面分离的情况,文字显示的位置正确,但保持在屏幕的最上端,当有其它窗口 + D) P1 d! t+ k1 w$ a; `# l5 h6 j Y( q
经过时也会显示文字。难道HDC也要设置Clipper,不会吧,真不知道怎么解决?!
5 G5 J" ^ ?$ T6 ?) Y6 U1 N, i, X* a6 j另外是不是可以附加个覆盖页面(overlay),用来显示文字;但覆盖页面GetDC会失败,不能Textout,怎样才能在覆盖页面上显示文字?!
4 c" n. K3 v) y+ Z, ^7 }) X--------------------------------------------------------------------------------' h. g- X- e U' M1 G4 j& z
第5个回答3 x7 H' b% w5 t
我也做过这事,,我的方法是注入一个dll,枚举它当前程序里所有的surface,然后分别往枚举出来的surface上textout,看哪个能用,效果最好
9 I4 |- q' m* Z2 V
1 Y* Z( _/ y, GC/C++ code
# ^" l: A _9 {" N. f) S--------------------------------------------------------------------------------. L+ u' O. Z+ z. O
LPDIRECTDRAWSURFACE7 lpDDSPrimary;//主surface
, o# n! F, ^1 A2 Z/ n8 K% {: DLPDIRECTDRAWSURFACE7 lpDDS[4];//用来保存枚举出的surface9 r; s f9 S" b& A/ [
DWORD lpDDAddr = 0x00160e50;//lpDD的地址,通过调试很容易得到
" k8 z4 q' y# L* V0 }* SLPDIRECTDRAW7 lpDD;
% M5 @1 V# u) M8 X/ C' EDDSURFACEDESC2 ddsd;
- u* w: b5 j5 K$ f4 H- a* p' g9 C& L& c9 N9 L$ L1 v
int si=0;//surface计数- M& U( x+ k D& s
DDSCAPS2 ddscaps ;
4 v2 s$ I( J) X/ W' I; }; |8 UHRESULT WINAPI _surfaceEnumCallback_GetPrimary( LPDIRECTDRAWSURFACE7 lpDDSurface, LPDDSURFACEDESC2 lpDDSurfaceDesc, LPVOID /*lpContext*/ ) {& p( X2 _- g4 {% n4 Y# U+ P% s
lpDDS[si] = lpDDSurface;
+ f, D' ^' B, e4 h4 s9 I si++;
, m! }# w- E' p6 @2 ] wsprintf(buff2, "surface:%8x, width=%d, height=%d, buffCount:%d\n",: f" d4 D8 h- \6 v- F# X) M" J/ k
lpDDSurface, lpDDSurfaceDesc->dwWidth,
: E1 r% t$ V4 D4 R lpDDSurfaceDesc->dwHeight,lpDDSurfaceDesc->dwBackBufferCount);' t! t) G- z& J* R( Z
mout(buff2);6 i2 U( P Q3 W9 Z) y8 C1 H! ~' X
if( lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE ) { //Primary
6 F8 k2 b7 j. _' ?* e/ A- D* E lpDDSPrimary = lpDDSurface;
1 ^+ [$ |+ I3 L* J2 f wsprintf(buff2, "primary surface: %8x\n", lpDDSurface);2 F8 d- |7 M3 L* N. ]0 _3 \
mout(buff2);& L6 b6 w% y7 O* j
// lpDDSurface->GetSurfaceDesc(&ddsd);' p, E( _. n8 H
// return DDENUMRET_CANCEL;6 `( h! H' u- R- j
}
- ^ r5 f- ^8 G0 h //lpDDSurface->Release();6 ~4 |/ M$ X B5 P
return DDENUMRET_OK;! s8 t5 W. v. S7 I2 C3 T
}
# u3 S" c" n, L2 v//以上是回调函数,下面是枚举
2 b, \' T) A6 K6 A// Get lpDD4 w8 R- @# \7 t' a- z3 b8 }- T
DWORD addr=0x00385b2c;4 C* y( M( A6 e
VirtualProtect( ( void * ) addr, 4, PAGE_EXECUTE_READWRITE, &dwOldProtect );% }" t% j; q" C+ |6 {5 r6 `
lpDDAddr= *((DWORD*)addr);( m/ h* [/ N: ~- ~4 `
lpDD = (struct IDirectDraw7 *)lpDDAddr;
' }4 `; `& l7 t7 V2 M( x) L1 |& K' l: R/ [1 ]
// Enum Surface
7 _9 o1 P& t8 f0 W6 N- Mmout("now start to enum:\n");& R2 s. N& C( ~' h1 F- k" _
lpDD->EnumSurfaces( DDENUMSURFACES_DOESEXIST | DDENUMSURFACES_ALL, NULL, NULL, _surfaceEnumCallback_GetPrimary );
; y) A3 u9 e3 qfor(int i=0;i<4;i++){: W# z# c4 Y, r4 n, V1 X/ I
wsprintf(buff2, "found surface[%d]: %8x\n", i, lpDDS);0 e" P5 K7 c" ]
mout(buff2);! a1 G# W9 R% q
}) u* Q( B9 ^+ }2 o6 R! K8 I" z2 Z
% p. u3 ]1 B" l
/ Z. J, A& ~0 t: c0 O--------------------------------------------------------------------------------5 t- V% u. A; H- c1 F
第6个回答
6 f2 Y1 q% F j2 p% c; W0 M2 \帮顶
) N9 U0 j; _" T+ O$ W2 `--------------------------------------------------------------------------------3 J2 r1 _6 N( N4 T
第7个回答6 X9 n* u! q! D; y
在它的backBuffer绘制试试。
. v& `; c- s6 t& E--------------------------------------------------------------------------------
2 h& s2 v; f% Y6 I l第8个回答" F5 ]% ]# i4 S
backBuffer 无法GetDC(),就无法TextOut 7 i& c2 F- Z/ t5 K8 V
--------------------------------------------------------------------------------
' n" R( g% {- F! o8 Z第9个回答
& ^' Y- D# z5 u6 E! o6 L4 |% cbackBuffer怎么会无法GetDC呢?那那个程序本身是怎么往上绘东西的啊。你看看是不是其它地方错了。
' j% C5 h9 Y( Z--------------------------------------------------------------------------------# _0 Z5 m% F4 [8 G( X7 V! g' |+ _
第10个回答: V' n: q, `0 e. H2 }9 r
不会有错,那个程序是解码MP4视频流数据后,用ddraw加以显示,程序本身用不到GetDC,我用是为了显示文字。 4 F- O* }% w* D( s
--------------------------------------------------------------------------------' R% F% F4 L( y/ E, t" |% M
第11个回答( ^, B" N/ e9 F% ~, d+ a9 n% G; V
那程序要往上面绘东西,Blt总得支持吧?
7 w5 i3 m# Y8 C! R9 m你自己建一个Surface,GetDC后TextOut你的文字,然后Blt到那个BackBuffer上去。 $ p2 H: M7 w' K/ r
-------------------------------------------------------------------------------- |