下面这对对话在研究使用directdraw的游戏汉化时可能能用上。
o9 p( s% s: e5 R: m" e3 h0 }' t
! D: A% w. a" R+ N1 t原文; U! `) |; S1 c4 g5 `1 t
http://www.qqgb.com/Program/VC/VCJQ/Program_177879.html
# Q% ]- i8 P+ U6 X: _5 w
) i! V% r* |5 G2 I8 sdirectdraw主表面显示文字问题 前提:已经Hook了ddraw.dll的几个关键API(包括接口的虚函数表),成功获取到了主表面。 . L; M* M2 m0 y2 h% t
问题:向主表面的HDC TextOut后,文字是显示出来了,但都保持在屏幕的最顶层,其它窗口经过时也会显示文字。 6 C3 n6 o0 N7 E0 @
为什么没有附在原窗口(用来显示主表面的)中呢? 第1个回答
1 k8 I0 v# Y* Y/ L$ A# O居然还有这种事?HDC是ddraw窗口的DC吗?一个DC绘制的图形不是分离的对象,不可能被拆成两部分显示。后台表面也要同时hook绘制。 7 _/ U4 d' p5 p
--------------------------------------------------------------------------------: D: B! F- `1 v
第2个回答. C6 B8 x3 t6 O
HDC 是主表面实例指针-> GetDC()的,不是窗口的HDC。后台表面GetDC()失败,应该不是真正的后台,它不是用Flip进行显示的,而是主表面用Blt绘制另外一个非主表面。 ( @9 x" i9 e( {8 f9 ?( v
--------------------------------------------------------------------------------
! `$ M( _5 X! s$ ^9 B6 k第3个回答/ p0 a3 f8 A/ q% i
窗口界面的DDraw程序肯定不可能使用Flip了。
/ u, @- Z; I! U1 b主表面上绘制东西出界是常有的事情,首先要设置Clipper,而且在绘制的时候还要自己获取窗口坐标进行坐标变换,这样才能保证绘制在窗口上。 % K$ Z) W' S! d5 Q! W6 C
--------------------------------------------------------------------------------7 d9 a6 p& H4 K5 U3 }( f
第4个回答
) N, I3 |9 | P7 [' y我是想在第3方的视频播放器中显示文字,已经Hook了DDraw.dll,得到了主表面实例指针lpddsPrimary,此时主表面已经设置过了Clipper, % G0 x- M7 R5 _& j" _+ u/ c
我只是lpddsPrimary-> GetDC(),然后Textout,出现显示的文字和画面分离的情况,文字显示的位置正确,但保持在屏幕的最上端,当有其它窗口
- ~- \, S- r3 ^: y' d+ D. L经过时也会显示文字。难道HDC也要设置Clipper,不会吧,真不知道怎么解决?! 2 d* u* c3 z% A2 Q* ~
另外是不是可以附加个覆盖页面(overlay),用来显示文字;但覆盖页面GetDC会失败,不能Textout,怎样才能在覆盖页面上显示文字?! 8 a; L! v5 R: _5 e/ x& q/ A
--------------------------------------------------------------------------------( V6 a/ z1 h* Z) }' b" i
第5个回答! a0 ]6 A' {; V4 g8 o! w" Z
我也做过这事,,我的方法是注入一个dll,枚举它当前程序里所有的surface,然后分别往枚举出来的surface上textout,看哪个能用,效果最好 % e+ t$ ^5 X& z6 [" } T
6 t9 r* t' p6 }/ m
C/C++ code- D- F4 U- F' d E& U
--------------------------------------------------------------------------------; W1 X9 _" Z6 e- n& w
LPDIRECTDRAWSURFACE7 lpDDSPrimary;//主surface
0 f5 C) O# }/ r& X$ j& V' cLPDIRECTDRAWSURFACE7 lpDDS[4];//用来保存枚举出的surface
# x8 ?' X1 ^, e1 N6 r$ z) iDWORD lpDDAddr = 0x00160e50;//lpDD的地址,通过调试很容易得到0 Y9 G( M0 U1 K6 z+ e
LPDIRECTDRAW7 lpDD;# H5 ]3 P: ?1 m0 S
DDSURFACEDESC2 ddsd;
- w4 h7 Z) M [$ B' [
4 d4 Z9 X+ d, x- c! g& c. d4 }7 oint si=0;//surface计数
: I5 A: ~4 a5 C) W7 K, F7 MDDSCAPS2 ddscaps ;9 l* Q8 n+ T* t w6 _; n. ]
HRESULT WINAPI _surfaceEnumCallback_GetPrimary( LPDIRECTDRAWSURFACE7 lpDDSurface, LPDDSURFACEDESC2 lpDDSurfaceDesc, LPVOID /*lpContext*/ ) {7 T; t7 C0 H% N+ x$ u* z5 S0 [2 I+ f
lpDDS[si] = lpDDSurface;
; T# e1 ], w' N+ K' e" }: P si++;: [% \# n# |9 g. W# ~; A
wsprintf(buff2, "surface:%8x, width=%d, height=%d, buffCount:%d\n",) ^: ^+ S5 V0 \$ R
lpDDSurface, lpDDSurfaceDesc->dwWidth,
! F& L4 s2 i& h! j lpDDSurfaceDesc->dwHeight,lpDDSurfaceDesc->dwBackBufferCount);- f8 q7 _: k7 s! L1 \) G
mout(buff2);
- @5 [& W+ G0 [3 Y) V: Z if( lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE ) { //Primary0 v |- L' \3 h( N% A P
lpDDSPrimary = lpDDSurface;2 S" ^8 x% D; |* i1 N
wsprintf(buff2, "primary surface: %8x\n", lpDDSurface);
+ v* B/ q. r; T mout(buff2);
A" h% f9 z) `& I // lpDDSurface->GetSurfaceDesc(&ddsd);
1 }' }. L/ T. h7 a+ N // return DDENUMRET_CANCEL;
/ a/ M5 j/ ^4 G, a% v. }! z \ }
) h- h: u/ N, s4 @7 J& [4 E" |: M //lpDDSurface->Release();/ j# S0 K! L' u: e B
return DDENUMRET_OK;, t9 Z6 J* K; x6 H) @) D
}! ~" I0 o+ ?0 W
//以上是回调函数,下面是枚举+ b( F4 {* B5 p. w, S7 ^% l
// Get lpDD2 {( j5 E/ P U
DWORD addr=0x00385b2c;
$ q7 W0 v- F WVirtualProtect( ( void * ) addr, 4, PAGE_EXECUTE_READWRITE, &dwOldProtect );
$ g, R. o' J5 b1 n3 S7 Q3 vlpDDAddr= *((DWORD*)addr);
0 K7 N6 s+ Z0 ^6 p1 n- o2 B y6 W9 M" flpDD = (struct IDirectDraw7 *)lpDDAddr;' B/ T6 u: C& x# f8 d6 @
5 ]1 z* J* K" M1 \
// Enum Surface
& y4 P' c7 h$ f% l$ Qmout("now start to enum:\n");
$ W. ?8 F; w. R" ^$ g9 v$ @lpDD->EnumSurfaces( DDENUMSURFACES_DOESEXIST | DDENUMSURFACES_ALL, NULL, NULL, _surfaceEnumCallback_GetPrimary );
/ c) y, s5 h8 W, Qfor(int i=0;i<4;i++){: E: @+ F1 ]( B. q9 {1 n
wsprintf(buff2, "found surface[%d]: %8x\n", i, lpDDS);
6 ~ G9 p( {" j3 Y" G9 y$ x mout(buff2);
# K3 Q$ [0 ?1 b2 P}/ T- e( Q }4 N2 S \* h, s
0 L+ Y7 l, x" w! ?" @# S
9 e4 f; b" x& x* _9 B0 n* |% `--------------------------------------------------------------------------------) G5 L* ^. K% l6 U/ l
第6个回答
6 Y u- O8 J& Q/ A$ I% b, a帮顶
! _8 f- F- d/ Z) i2 W--------------------------------------------------------------------------------) s7 K4 T' \" w6 H( A, L
第7个回答
& S* d% E4 E0 [' a" k& w在它的backBuffer绘制试试。 3 ?6 Y/ h1 O" M5 n( {7 m; d& M
--------------------------------------------------------------------------------
2 r% o- y! c: ?; J# }第8个回答: Z1 N( x5 C1 [! i/ }% O- e
backBuffer 无法GetDC(),就无法TextOut " O2 c) ^% L7 M1 M! Q, k6 W
--------------------------------------------------------------------------------6 ?; f6 e- q2 p9 L
第9个回答3 Y% u& v5 j3 u8 _4 I, O% G6 p
backBuffer怎么会无法GetDC呢?那那个程序本身是怎么往上绘东西的啊。你看看是不是其它地方错了。 * h. _* Q+ q4 _! T# z
--------------------------------------------------------------------------------
; }3 a) z" j" L% {, p; r8 B* @# k第10个回答
% t$ Z( D/ y/ P不会有错,那个程序是解码MP4视频流数据后,用ddraw加以显示,程序本身用不到GetDC,我用是为了显示文字。 7 ]; [/ B o! @. w
--------------------------------------------------------------------------------1 l$ Q, A3 b7 W# Z( I+ u) L
第11个回答
5 P% ?; U! k3 E7 ]: m- k那程序要往上面绘东西,Blt总得支持吧?
2 @% V, g, h: p- K2 J1 k你自己建一个Surface,GetDC后TextOut你的文字,然后Blt到那个BackBuffer上去。 ' h7 s8 [4 c/ U
-------------------------------------------------------------------------------- |