下面这对对话在研究使用directdraw的游戏汉化时可能能用上。9 p& M5 t3 @- G- Y( e. E
# N2 s+ Y% X/ A( l9 ]+ Q原文
- {. ?/ B0 v) ^2 M2 q) j1 [http://www.qqgb.com/Program/VC/VCJQ/Program_177879.html / A0 P" e+ {8 ]" k3 |4 s {
& J8 U" }7 P) Y* [' j
directdraw主表面显示文字问题 前提:已经Hook了ddraw.dll的几个关键API(包括接口的虚函数表),成功获取到了主表面。 $ R/ R% J9 Q% R2 r
问题:向主表面的HDC TextOut后,文字是显示出来了,但都保持在屏幕的最顶层,其它窗口经过时也会显示文字。 8 W2 ]1 P2 @( E# x6 G
为什么没有附在原窗口(用来显示主表面的)中呢? 第1个回答
, U5 Z- n* ?9 X: v0 s. w居然还有这种事?HDC是ddraw窗口的DC吗?一个DC绘制的图形不是分离的对象,不可能被拆成两部分显示。后台表面也要同时hook绘制。
! ]' w6 ?1 _- h8 v+ ^--------------------------------------------------------------------------------
. N7 f& I c+ q& c, G# X2 t% h第2个回答, ^2 k! F" x8 k" U8 _/ M7 _
HDC 是主表面实例指针-> GetDC()的,不是窗口的HDC。后台表面GetDC()失败,应该不是真正的后台,它不是用Flip进行显示的,而是主表面用Blt绘制另外一个非主表面。
" ?' x Q+ W0 G8 x) f O# R--------------------------------------------------------------------------------/ E3 z. @4 }. R R
第3个回答
8 H: r* k' p. g: B3 `! E$ _+ q窗口界面的DDraw程序肯定不可能使用Flip了。 " z* f$ i, o: `8 H( w V! R1 H
主表面上绘制东西出界是常有的事情,首先要设置Clipper,而且在绘制的时候还要自己获取窗口坐标进行坐标变换,这样才能保证绘制在窗口上。
2 V; W/ x( V& A2 }3 u; M) b4 ~--------------------------------------------------------------------------------- S( ?) A) L0 N5 h1 C3 D% l P- h
第4个回答* _, T/ m& @8 y, p, _- I
我是想在第3方的视频播放器中显示文字,已经Hook了DDraw.dll,得到了主表面实例指针lpddsPrimary,此时主表面已经设置过了Clipper, . a, d a6 ~% h7 ], y2 p, Q. o( g$ |
我只是lpddsPrimary-> GetDC(),然后Textout,出现显示的文字和画面分离的情况,文字显示的位置正确,但保持在屏幕的最上端,当有其它窗口
) r. V9 m8 D( i3 h l经过时也会显示文字。难道HDC也要设置Clipper,不会吧,真不知道怎么解决?!
$ \7 w# x' M% }# J' T! }另外是不是可以附加个覆盖页面(overlay),用来显示文字;但覆盖页面GetDC会失败,不能Textout,怎样才能在覆盖页面上显示文字?!
; Y+ k- j" i" p+ A--------------------------------------------------------------------------------
# Z- d ]/ m2 f" A. R第5个回答
: S& P& ?) j' f7 B/ A我也做过这事,,我的方法是注入一个dll,枚举它当前程序里所有的surface,然后分别往枚举出来的surface上textout,看哪个能用,效果最好
: ]# X' F* Q: ~7 }, T1 F3 F! v# C" C- d$ Y1 e
C/C++ code. e# H' d# R4 W9 ^1 r3 y G
--------------------------------------------------------------------------------9 i! \/ u( P0 g/ E0 c
LPDIRECTDRAWSURFACE7 lpDDSPrimary;//主surface! K% \$ s# V2 T; Z
LPDIRECTDRAWSURFACE7 lpDDS[4];//用来保存枚举出的surface
0 [0 c; ~8 @' A/ EDWORD lpDDAddr = 0x00160e50;//lpDD的地址,通过调试很容易得到& [& h6 {! w1 z( U8 F; ?, O
LPDIRECTDRAW7 lpDD;0 k0 n/ Y. J% K0 p+ F1 {! x
DDSURFACEDESC2 ddsd;9 e6 ?" T. F2 `" s
4 ?0 |8 X X; ^3 o+ `( X/ Tint si=0;//surface计数6 q0 I+ T9 R1 \5 h1 [6 A
DDSCAPS2 ddscaps ;
) u3 a" r a0 k& iHRESULT WINAPI _surfaceEnumCallback_GetPrimary( LPDIRECTDRAWSURFACE7 lpDDSurface, LPDDSURFACEDESC2 lpDDSurfaceDesc, LPVOID /*lpContext*/ ) {& G a8 }; R" y! m0 X! A* P6 `# D
lpDDS[si] = lpDDSurface;
c5 P A, D. B, c% |. [% n si++;4 \# G% m, E7 v( V0 p
wsprintf(buff2, "surface:%8x, width=%d, height=%d, buffCount:%d\n",
0 F6 ~6 a9 n! F lpDDSurface, lpDDSurfaceDesc->dwWidth,
# s# V% I& A: m- C( @ lpDDSurfaceDesc->dwHeight,lpDDSurfaceDesc->dwBackBufferCount);! L& \7 y" E& W2 D
mout(buff2);
7 X, u! H+ ]6 `0 O- u; L$ q; {8 T if( lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE ) { //Primary
. o% U" Z5 b+ L1 m4 f; U& x lpDDSPrimary = lpDDSurface;
& S3 Z1 J0 L- {. l wsprintf(buff2, "primary surface: %8x\n", lpDDSurface);
( K' @* n6 o: U4 e! }+ O0 i mout(buff2);
) n+ h) _& D) \; R8 }* V* k' k# G // lpDDSurface->GetSurfaceDesc(&ddsd);& Z. F) y- p+ C M
// return DDENUMRET_CANCEL;
) N! l9 Q$ D# c; S! S% _ }
1 K! i$ n X* R' s //lpDDSurface->Release();
- |% E; ^+ a0 ?# R( @7 K6 t3 K return DDENUMRET_OK;
* ^ q* i$ u8 x0 y0 k$ x+ O}" [) x" h$ @' z! N5 z6 q. e# Y
//以上是回调函数,下面是枚举
8 H( C! h; i4 e5 f, P5 C: @// Get lpDD) z3 D( \6 ~/ h' @7 C# I9 x) H
DWORD addr=0x00385b2c;
. L) D& F) ?2 V6 KVirtualProtect( ( void * ) addr, 4, PAGE_EXECUTE_READWRITE, &dwOldProtect );) [* V6 g; P$ ?3 f3 F8 \6 @
lpDDAddr= *((DWORD*)addr);9 v6 P+ l' K* \- X
lpDD = (struct IDirectDraw7 *)lpDDAddr;
4 U' J# r" T: j
3 R' Z5 g& r/ m1 t6 v// Enum Surface
+ q1 m- u+ G0 p4 }2 b# d1 E! Nmout("now start to enum:\n");
9 i, n" }1 ]' J# U9 g" O, Q6 ulpDD->EnumSurfaces( DDENUMSURFACES_DOESEXIST | DDENUMSURFACES_ALL, NULL, NULL, _surfaceEnumCallback_GetPrimary );
# A1 A5 o! X$ l E3 i- S+ K. yfor(int i=0;i<4;i++){3 C& S8 V- T6 {3 ?
wsprintf(buff2, "found surface[%d]: %8x\n", i, lpDDS);
: D4 E! c" [( D$ X3 l mout(buff2);
9 ~* l& D/ B" H2 [: @0 ?$ ~0 v; \ i}
5 }3 A! ]; q) J" X* \7 K, g
& \* x) h# f1 O% P- ]( A9 y% q5 {! F3 i9 X+ \
--------------------------------------------------------------------------------
# w& C$ ]# g( N' w" ^9 l; m第6个回答0 J) `6 e* I% W l' h
帮顶 5 [0 K6 Y& l6 ?' z! ?
--------------------------------------------------------------------------------$ f1 `7 G) x* k7 P6 I. a
第7个回答
I2 b; U# t8 g V% S在它的backBuffer绘制试试。
% f; F1 x9 J% L0 j( t9 S--------------------------------------------------------------------------------6 `* v( R' w. |! Z6 l& T
第8个回答! S8 Y& B' ^+ d- p- N. K( p6 X0 N; V
backBuffer 无法GetDC(),就无法TextOut 6 v1 }- V- O" o* L9 |$ {
--------------------------------------------------------------------------------- G0 Q6 }# A- p+ N6 F7 ?; q
第9个回答
t! Q: k* B k- m, Q$ j/ |% pbackBuffer怎么会无法GetDC呢?那那个程序本身是怎么往上绘东西的啊。你看看是不是其它地方错了。
$ p0 ?+ r7 }: t--------------------------------------------------------------------------------
$ {: d& e% z7 r9 P4 G$ R第10个回答$ C$ G l/ k( O( G
不会有错,那个程序是解码MP4视频流数据后,用ddraw加以显示,程序本身用不到GetDC,我用是为了显示文字。 : f( a$ \+ |7 S/ C% @3 d- [
--------------------------------------------------------------------------------/ e" \0 x6 N/ C- Q! B
第11个回答4 n- [! n! ] Z! h+ _
那程序要往上面绘东西,Blt总得支持吧?
/ d8 V3 V/ G* l) E5 Z7 O你自己建一个Surface,GetDC后TextOut你的文字,然后Blt到那个BackBuffer上去。
& g! A+ k2 e" M0 b-------------------------------------------------------------------------------- |