下面这对对话在研究使用directdraw的游戏汉化时可能能用上。
) ]$ ?; s4 d* h y( u" U$ n
4 Y% [# a( f I$ L, V6 Y& Y原文
* A" E) l# N: o! Thttp://www.qqgb.com/Program/VC/VCJQ/Program_177879.html ! D' j' l$ K7 _0 w6 {
( L( m: _9 x" `& b$ }directdraw主表面显示文字问题 前提:已经Hook了ddraw.dll的几个关键API(包括接口的虚函数表),成功获取到了主表面。 4 g" q4 X5 ^4 z; K2 T
问题:向主表面的HDC TextOut后,文字是显示出来了,但都保持在屏幕的最顶层,其它窗口经过时也会显示文字。 ) c4 ]5 `4 U6 D- z, K; L
为什么没有附在原窗口(用来显示主表面的)中呢? 第1个回答! K3 Y5 z, X% Y4 \3 M6 X
居然还有这种事?HDC是ddraw窗口的DC吗?一个DC绘制的图形不是分离的对象,不可能被拆成两部分显示。后台表面也要同时hook绘制。 ! e8 i: z: S2 m" f: s
--------------------------------------------------------------------------------
8 X( E% @" c$ y第2个回答9 Q# r; s- }+ {& p
HDC 是主表面实例指针-> GetDC()的,不是窗口的HDC。后台表面GetDC()失败,应该不是真正的后台,它不是用Flip进行显示的,而是主表面用Blt绘制另外一个非主表面。
' @7 {1 V4 H' r* ?+ l6 M--------------------------------------------------------------------------------! z6 v, @0 ?6 v5 N, C* ~$ W
第3个回答4 T- r: C6 \' m( b' h
窗口界面的DDraw程序肯定不可能使用Flip了。
' M4 @( Q6 b5 e; l) n主表面上绘制东西出界是常有的事情,首先要设置Clipper,而且在绘制的时候还要自己获取窗口坐标进行坐标变换,这样才能保证绘制在窗口上。 5 ]& n: n2 u+ g+ [. ]
--------------------------------------------------------------------------------
" A6 \& o2 v. \1 h% e. s: ~第4个回答
9 v& x1 T; H2 C8 P& k0 G) w我是想在第3方的视频播放器中显示文字,已经Hook了DDraw.dll,得到了主表面实例指针lpddsPrimary,此时主表面已经设置过了Clipper, # j Y2 U" o! G/ M
我只是lpddsPrimary-> GetDC(),然后Textout,出现显示的文字和画面分离的情况,文字显示的位置正确,但保持在屏幕的最上端,当有其它窗口 ! Y7 i) d3 I' d) T1 Y
经过时也会显示文字。难道HDC也要设置Clipper,不会吧,真不知道怎么解决?!
/ E0 Q3 ]1 W6 }4 `& A9 ^: h另外是不是可以附加个覆盖页面(overlay),用来显示文字;但覆盖页面GetDC会失败,不能Textout,怎样才能在覆盖页面上显示文字?! . J1 H1 e% a4 \* m5 P
--------------------------------------------------------------------------------
5 {) [* m% G5 Z( d第5个回答
( ?0 Z! G! R8 u, a3 z5 s7 N0 }, x7 A* f我也做过这事,,我的方法是注入一个dll,枚举它当前程序里所有的surface,然后分别往枚举出来的surface上textout,看哪个能用,效果最好 ( C' A. E' ?5 g; l+ }1 m
, v( z, T4 i4 Q$ _C/C++ code
* ^. U1 ?( t. W% d' M3 T2 d--------------------------------------------------------------------------------
+ Q2 x, k/ ]- i C8 q8 eLPDIRECTDRAWSURFACE7 lpDDSPrimary;//主surface' |4 i5 Z7 D$ ~3 u+ |. l
LPDIRECTDRAWSURFACE7 lpDDS[4];//用来保存枚举出的surface
" V& O* s& h7 }" ^3 T6 }0 DDWORD lpDDAddr = 0x00160e50;//lpDD的地址,通过调试很容易得到
" B4 a) ` K2 v5 u0 c2 KLPDIRECTDRAW7 lpDD;
1 @; R, F/ U, x; {8 r) nDDSURFACEDESC2 ddsd;
0 ~& f" s6 w$ J0 n* h6 V* h- B- v+ W( e. h6 d; a4 p A
int si=0;//surface计数
2 M' }! t6 @: ?$ _, ^$ gDDSCAPS2 ddscaps ;
, l/ O% q! d2 t9 W5 D8 QHRESULT WINAPI _surfaceEnumCallback_GetPrimary( LPDIRECTDRAWSURFACE7 lpDDSurface, LPDDSURFACEDESC2 lpDDSurfaceDesc, LPVOID /*lpContext*/ ) {0 T5 c& t* x0 V: H* H; T
lpDDS[si] = lpDDSurface;( [) e* u; E5 s! K
si++;
7 h2 f* ^1 v# g wsprintf(buff2, "surface:%8x, width=%d, height=%d, buffCount:%d\n",, y3 r; C" j# r* \0 f
lpDDSurface, lpDDSurfaceDesc->dwWidth,$ I$ J" c8 \$ e, s* m
lpDDSurfaceDesc->dwHeight,lpDDSurfaceDesc->dwBackBufferCount);, Q- P6 f+ T) e/ {" n3 \
mout(buff2);
W- j" K1 D/ A) B% Y1 T if( lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE ) { //Primary
) Q' H u5 Z. I$ S lpDDSPrimary = lpDDSurface;, W9 b4 p# c8 c7 T8 A
wsprintf(buff2, "primary surface: %8x\n", lpDDSurface);
/ e5 j3 u1 v+ y4 A3 G mout(buff2);1 M( ]$ ]' S% |. E
// lpDDSurface->GetSurfaceDesc(&ddsd);( x* i2 b8 \- g& k+ a4 s9 Z
// return DDENUMRET_CANCEL;
" l9 R( E) J1 ]- G } % L8 G# M/ f0 {8 ]
//lpDDSurface->Release();& l, f* m! Y* ?$ t. d
return DDENUMRET_OK;' c! n# I5 r K5 |
}
5 D2 X1 ?7 r/ u$ L//以上是回调函数,下面是枚举% b4 |* B' C3 X( L" t0 i0 k
// Get lpDD
. {( b* l3 F: a: o8 {DWORD addr=0x00385b2c;
% ]0 n0 V# G l% n) r; {VirtualProtect( ( void * ) addr, 4, PAGE_EXECUTE_READWRITE, &dwOldProtect );7 l! f! {0 e b1 |# B; P
lpDDAddr= *((DWORD*)addr); m2 i' W4 B5 }: G# {
lpDD = (struct IDirectDraw7 *)lpDDAddr;
% ?( @, N) C9 R# n5 I, E/ H/ H! L, O4 r: B- \' N
// Enum Surface
9 |8 r2 K; F0 Smout("now start to enum:\n");
5 d" y' h7 S9 ?9 A1 e( SlpDD->EnumSurfaces( DDENUMSURFACES_DOESEXIST | DDENUMSURFACES_ALL, NULL, NULL, _surfaceEnumCallback_GetPrimary );; N: I9 R( d# h" S8 E
for(int i=0;i<4;i++){
+ B* ]! V# h' D7 g wsprintf(buff2, "found surface[%d]: %8x\n", i, lpDDS);/ D+ _& T j' Y8 e3 X2 }) Z4 d( x
mout(buff2);6 S2 x9 Q& k- Q) j" {8 e! s o" W2 |3 C
}5 A" D- L* r% ]. ^0 a5 D- _! @* q
' x( B# y D, o8 U( w0 Z
7 J+ q7 u1 R5 A ]% Z--------------------------------------------------------------------------------
) w! J& j- K7 I7 T第6个回答
+ h) ]- Q$ v. _: _8 G$ M帮顶 9 a/ S: R$ j# @8 u# J5 o
--------------------------------------------------------------------------------
9 I- [+ }! S/ I# ?# r* ~$ N' K- o第7个回答: x. f( J4 O& Q# U/ j2 t# a# ?- H
在它的backBuffer绘制试试。
, ~+ U5 w: g3 J/ V--------------------------------------------------------------------------------3 [8 @0 ?! ]- |/ a
第8个回答, |7 o# Q. }; `1 C" T' t
backBuffer 无法GetDC(),就无法TextOut + o3 @* {3 t' ]: l1 t, G+ C7 ]4 K
--------------------------------------------------------------------------------! q5 N/ O$ J; V
第9个回答/ e! M* Q+ ~/ i# s6 V9 D
backBuffer怎么会无法GetDC呢?那那个程序本身是怎么往上绘东西的啊。你看看是不是其它地方错了。 v* p. P( W6 x" m- F! c1 W, ?
--------------------------------------------------------------------------------$ c/ N2 B) \* v, ?$ Y. X' Z
第10个回答
% S+ E: A* u: N$ p$ J3 J不会有错,那个程序是解码MP4视频流数据后,用ddraw加以显示,程序本身用不到GetDC,我用是为了显示文字。
@: Q3 D; ~+ p) z& n! z--------------------------------------------------------------------------------
1 f8 f8 Q. M) k第11个回答
; ~9 Q" U, W0 s# W- a5 `0 c那程序要往上面绘东西,Blt总得支持吧?
% Z9 r5 k, c5 `; T- k4 w: |. [' N你自己建一个Surface,GetDC后TextOut你的文字,然后Blt到那个BackBuffer上去。 % `+ C+ Q* t0 d$ Z9 S
-------------------------------------------------------------------------------- |