下面这对对话在研究使用directdraw的游戏汉化时可能能用上。
6 J. M# L9 t5 f4 d& s+ d1 ]* J; B9 L8 g* l
原文 q0 i7 L# m4 Z3 m8 E
http://www.qqgb.com/Program/VC/VCJQ/Program_177879.html
E. Z# F! ~% u: B) \3 |1 B! j& E+ o
directdraw主表面显示文字问题 前提:已经Hook了ddraw.dll的几个关键API(包括接口的虚函数表),成功获取到了主表面。 4 B0 f$ ~& }. O. ^: ^
问题:向主表面的HDC TextOut后,文字是显示出来了,但都保持在屏幕的最顶层,其它窗口经过时也会显示文字。
3 t: d& m+ i3 k* g0 E为什么没有附在原窗口(用来显示主表面的)中呢? 第1个回答
' s. Q, j5 [ A9 p居然还有这种事?HDC是ddraw窗口的DC吗?一个DC绘制的图形不是分离的对象,不可能被拆成两部分显示。后台表面也要同时hook绘制。
8 y' ^6 H6 i9 o% e8 j( U--------------------------------------------------------------------------------! t1 ^5 U4 m* y% F
第2个回答& Z/ [1 N$ ^/ ^6 b! V2 ?8 l. R
HDC 是主表面实例指针-> GetDC()的,不是窗口的HDC。后台表面GetDC()失败,应该不是真正的后台,它不是用Flip进行显示的,而是主表面用Blt绘制另外一个非主表面。 & y2 [) B$ u7 ?
--------------------------------------------------------------------------------
F; h) T/ G4 }1 n* H, N: ?! J第3个回答9 `; I4 K, |$ J6 o }3 d6 a
窗口界面的DDraw程序肯定不可能使用Flip了。 5 ^4 i/ i& |: z n) w
主表面上绘制东西出界是常有的事情,首先要设置Clipper,而且在绘制的时候还要自己获取窗口坐标进行坐标变换,这样才能保证绘制在窗口上。 4 N/ c p+ K- O4 g: p
--------------------------------------------------------------------------------3 M7 Y+ ?7 B8 e
第4个回答* {* @ F ?1 e" X7 ~& x
我是想在第3方的视频播放器中显示文字,已经Hook了DDraw.dll,得到了主表面实例指针lpddsPrimary,此时主表面已经设置过了Clipper, $ V' T. B* f B7 s* m9 l7 {
我只是lpddsPrimary-> GetDC(),然后Textout,出现显示的文字和画面分离的情况,文字显示的位置正确,但保持在屏幕的最上端,当有其它窗口
& J$ `! V$ T- y% ~0 h! z8 {经过时也会显示文字。难道HDC也要设置Clipper,不会吧,真不知道怎么解决?!
2 L0 @2 x* e) w; r( f另外是不是可以附加个覆盖页面(overlay),用来显示文字;但覆盖页面GetDC会失败,不能Textout,怎样才能在覆盖页面上显示文字?!
8 ^6 D/ D5 t0 }( E1 |/ R' }-------------------------------------------------------------------------------- Y9 R9 r- [ E# j3 ^
第5个回答. v7 L8 p# I" H# J# Z, |7 m
我也做过这事,,我的方法是注入一个dll,枚举它当前程序里所有的surface,然后分别往枚举出来的surface上textout,看哪个能用,效果最好
Q7 \: B& `. n: \. c p$ _& {$ U3 X: t9 U, M, g! l, H ~
C/C++ code
" H6 p2 i3 z3 q# Q% j--------------------------------------------------------------------------------* q+ v; k9 y6 u' ~
LPDIRECTDRAWSURFACE7 lpDDSPrimary;//主surface" W2 z. x# S7 ^) ~% k$ J5 \
LPDIRECTDRAWSURFACE7 lpDDS[4];//用来保存枚举出的surface
6 y3 A8 V" w7 i' u% L# N3 kDWORD lpDDAddr = 0x00160e50;//lpDD的地址,通过调试很容易得到
8 B8 y% h0 w, [ A1 N7 P: a C! lLPDIRECTDRAW7 lpDD;
8 [. C0 i% u( }* s1 w: z, NDDSURFACEDESC2 ddsd;
- d5 u8 u" I |+ a# s! S5 N; z9 z& v& x
int si=0;//surface计数
/ X1 v ]6 H; l! S' I: `1 E4 W$ GDDSCAPS2 ddscaps ;2 z5 T' H% K1 v- u9 a- `3 D) c
HRESULT WINAPI _surfaceEnumCallback_GetPrimary( LPDIRECTDRAWSURFACE7 lpDDSurface, LPDDSURFACEDESC2 lpDDSurfaceDesc, LPVOID /*lpContext*/ ) { t8 T9 _+ ?5 v
lpDDS[si] = lpDDSurface;
0 b; n" o# H Z5 M$ m- |; K si++;
0 i6 ?# l# m; c/ h5 \, ~+ r, {6 X4 ^" P, q wsprintf(buff2, "surface:%8x, width=%d, height=%d, buffCount:%d\n",# _* n3 Z+ X. N, I l# k
lpDDSurface, lpDDSurfaceDesc->dwWidth,
4 E6 v( `+ k" A& C lpDDSurfaceDesc->dwHeight,lpDDSurfaceDesc->dwBackBufferCount);" c1 h$ N, f$ v% E3 Q* u" P4 s
mout(buff2);
6 T1 E4 D, K/ ^: b- | if( lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE ) { //Primary m' Q: s. d6 a: z$ }# B; [4 v8 ~- O
lpDDSPrimary = lpDDSurface;
0 b$ y& S& `: |. } P9 j7 v& ^. I wsprintf(buff2, "primary surface: %8x\n", lpDDSurface);1 x+ _, I. {9 r) I+ N8 S
mout(buff2);
7 [; C4 w+ d* @ // lpDDSurface->GetSurfaceDesc(&ddsd);0 T: a7 G3 H O
// return DDENUMRET_CANCEL;" ]( h: P2 v' c9 v* e# V% t3 Z6 w1 u
} C* l: t: m; C/ N
//lpDDSurface->Release();
" o- f: Q2 `% R. o ?0 j return DDENUMRET_OK;
% q6 N( y, d# W; a K}
6 C* t: q, l4 k6 q& [//以上是回调函数,下面是枚举
$ M0 g1 o- x; \// Get lpDD
/ \% b% W2 s1 D) sDWORD addr=0x00385b2c;' p+ {9 O% J* E. U3 K3 N5 j
VirtualProtect( ( void * ) addr, 4, PAGE_EXECUTE_READWRITE, &dwOldProtect );
! N* _, n$ h- S: ~ j' d- W& nlpDDAddr= *((DWORD*)addr);6 G* u* M- Q' \. f
lpDD = (struct IDirectDraw7 *)lpDDAddr;
+ i2 h7 j$ x K. H/ K" N8 S/ x' v% M4 c y8 Y/ Z
// Enum Surface
( q1 y1 ?6 {( H& umout("now start to enum:\n");
+ L; Z7 {8 ^$ p! R" AlpDD->EnumSurfaces( DDENUMSURFACES_DOESEXIST | DDENUMSURFACES_ALL, NULL, NULL, _surfaceEnumCallback_GetPrimary );
# C0 Q0 f$ u6 K: u% _for(int i=0;i<4;i++){1 E+ m. G8 C. F* C
wsprintf(buff2, "found surface[%d]: %8x\n", i, lpDDS);& l. S* A$ t. ~% k! a
mout(buff2);
( |$ R6 ?( t. v}
' V7 A9 q' k/ z4 o/ K. J
& ^3 {5 L; }+ l9 D9 ?# i
* X+ y8 E/ V4 J& T6 w--------------------------------------------------------------------------------
0 S6 H8 V& Z" n5 d* [# H第6个回答
F& X2 O$ C- P& Z( ^帮顶 6 J% a$ Y9 @; g
--------------------------------------------------------------------------------" j, H6 V# [1 L; J
第7个回答
1 ^& H, z/ F5 r/ z在它的backBuffer绘制试试。
- f* b, U2 B, j2 {3 j0 r( ^' T: Y m--------------------------------------------------------------------------------
9 l) L1 g. b5 Y, b Z. K8 j第8个回答
4 s: y* {0 R0 S" \! p* \backBuffer 无法GetDC(),就无法TextOut
$ R8 ~0 d- X$ [- M' U+ {--------------------------------------------------------------------------------( s( |8 h1 I/ N: D8 A$ s8 \
第9个回答
3 x7 u$ [8 W. F9 T8 sbackBuffer怎么会无法GetDC呢?那那个程序本身是怎么往上绘东西的啊。你看看是不是其它地方错了。
: B6 ]7 A. C6 z l: H--------------------------------------------------------------------------------
& i/ t4 U6 Q# ]! I9 o1 | V8 h! l第10个回答
' B/ `# m. I& Q不会有错,那个程序是解码MP4视频流数据后,用ddraw加以显示,程序本身用不到GetDC,我用是为了显示文字。 ' d" P( i/ E- J4 N
--------------------------------------------------------------------------------5 n. { |) {7 [- E
第11个回答' h4 ?# Z% K% R4 b% t0 i- p4 c
那程序要往上面绘东西,Blt总得支持吧? * }% ?8 G3 S0 j* h- r+ T- m" N
你自己建一个Surface,GetDC后TextOut你的文字,然后Blt到那个BackBuffer上去。 ) }. O1 W1 L8 T, D6 L
-------------------------------------------------------------------------------- |