下面这对对话在研究使用directdraw的游戏汉化时可能能用上。
: I2 S! X8 M+ e
/ `, N+ S% J9 G) [: R/ y( U原文# ~9 x" G- z0 x8 E: p- `5 i
http://www.qqgb.com/Program/VC/VCJQ/Program_177879.html
) T" l9 e- i3 ?4 J' R# C1 B; k& m& Q, q8 l. P z) @# K0 {
directdraw主表面显示文字问题 前提:已经Hook了ddraw.dll的几个关键API(包括接口的虚函数表),成功获取到了主表面。
) v7 c+ s- Y2 D" J7 F问题:向主表面的HDC TextOut后,文字是显示出来了,但都保持在屏幕的最顶层,其它窗口经过时也会显示文字。
. ]( l* q% a4 |) z# B为什么没有附在原窗口(用来显示主表面的)中呢? 第1个回答
% C# ~" y& }8 d4 F居然还有这种事?HDC是ddraw窗口的DC吗?一个DC绘制的图形不是分离的对象,不可能被拆成两部分显示。后台表面也要同时hook绘制。 9 F; G. m: \5 R' T6 S2 v9 ~
--------------------------------------------------------------------------------9 B4 w/ ?% z+ t: x" w ^) K3 V
第2个回答
' t/ v4 d+ X! H' k$ j- cHDC 是主表面实例指针-> GetDC()的,不是窗口的HDC。后台表面GetDC()失败,应该不是真正的后台,它不是用Flip进行显示的,而是主表面用Blt绘制另外一个非主表面。 - _6 ^+ p) i' A( S4 f
--------------------------------------------------------------------------------
7 }; b# y: g9 y( K3 [第3个回答
( H; c& X: ]. _1 y5 o# Z窗口界面的DDraw程序肯定不可能使用Flip了。 ) R, ~4 g: V! \5 w6 h
主表面上绘制东西出界是常有的事情,首先要设置Clipper,而且在绘制的时候还要自己获取窗口坐标进行坐标变换,这样才能保证绘制在窗口上。
, {2 D* |& M9 r. z) P) ~: p--------------------------------------------------------------------------------
& t) D7 p2 t4 _1 X4 U3 F3 s第4个回答" t2 G+ T" B6 S; r1 ~! t
我是想在第3方的视频播放器中显示文字,已经Hook了DDraw.dll,得到了主表面实例指针lpddsPrimary,此时主表面已经设置过了Clipper, $ z# T% q6 L% E' h0 b9 A
我只是lpddsPrimary-> GetDC(),然后Textout,出现显示的文字和画面分离的情况,文字显示的位置正确,但保持在屏幕的最上端,当有其它窗口 & }+ I: S5 n8 U4 F9 U) x! Z
经过时也会显示文字。难道HDC也要设置Clipper,不会吧,真不知道怎么解决?! , z/ F$ a9 c3 R/ j. B9 W9 s$ |9 i
另外是不是可以附加个覆盖页面(overlay),用来显示文字;但覆盖页面GetDC会失败,不能Textout,怎样才能在覆盖页面上显示文字?!
w. W* N. K: A6 P--------------------------------------------------------------------------------# ~- ~" i- Z6 c5 B
第5个回答0 A' W& Z5 B+ x* a
我也做过这事,,我的方法是注入一个dll,枚举它当前程序里所有的surface,然后分别往枚举出来的surface上textout,看哪个能用,效果最好 }+ }+ H& ~7 `# P# I) Q9 P
. B/ o0 s3 g0 I7 ?# ~* K
C/C++ code- x# \$ q; w! U3 q6 d6 T
--------------------------------------------------------------------------------
$ T6 O$ N5 w8 MLPDIRECTDRAWSURFACE7 lpDDSPrimary;//主surface5 Q) y( Q: T: l' u$ E: E; v
LPDIRECTDRAWSURFACE7 lpDDS[4];//用来保存枚举出的surface& i3 O! n5 y- M! w6 j. }6 S4 s
DWORD lpDDAddr = 0x00160e50;//lpDD的地址,通过调试很容易得到& A' f! o# z$ O- C/ f
LPDIRECTDRAW7 lpDD;, d( }( b3 s% j- F8 b0 [3 \6 J
DDSURFACEDESC2 ddsd;$ D& P( i/ G. r r# B
4 e2 R3 r$ F" \
int si=0;//surface计数
+ _9 [& I( {8 V: i) G; xDDSCAPS2 ddscaps ;
- {$ I# T: N- v0 ~ p7 R' oHRESULT WINAPI _surfaceEnumCallback_GetPrimary( LPDIRECTDRAWSURFACE7 lpDDSurface, LPDDSURFACEDESC2 lpDDSurfaceDesc, LPVOID /*lpContext*/ ) {
$ v2 x& T' | N# z7 f8 I lpDDS[si] = lpDDSurface;4 ?1 y; d7 _& g7 x
si++;
0 v, b0 [; R! I. ?3 U3 V& n+ p wsprintf(buff2, "surface:%8x, width=%d, height=%d, buffCount:%d\n",
* O+ ?" L* n( o+ } lpDDSurface, lpDDSurfaceDesc->dwWidth,, C+ o/ r4 s- w6 w9 B2 I
lpDDSurfaceDesc->dwHeight,lpDDSurfaceDesc->dwBackBufferCount);
. ~1 m& q/ z3 |! O! C5 ~, V mout(buff2);
; t/ V( V) `( y# p6 A if( lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE ) { //Primary
( p, h4 y4 } Z lpDDSPrimary = lpDDSurface;% a% u4 ~3 k, R" ]% F! c+ h' q
wsprintf(buff2, "primary surface: %8x\n", lpDDSurface);
3 P3 k3 a; w: K! O: A mout(buff2);
% j& ]& ]3 h( Z# a: q: a9 K // lpDDSurface->GetSurfaceDesc(&ddsd);
" b3 c3 K) c% f# ]( k( R // return DDENUMRET_CANCEL;
: k* i. l- u3 A } 6 \) S# ~: O( ?2 g
//lpDDSurface->Release();# p7 |; P9 p% N# @
return DDENUMRET_OK; E* q. W8 v6 X& ?! ~
}- i4 z/ [3 y3 v# \! I9 A/ |
//以上是回调函数,下面是枚举
7 o+ h, k' Q7 {- \+ d$ ~// Get lpDD
* @/ u8 a) Z* `DWORD addr=0x00385b2c;
/ }/ `% U. {+ x$ i3 PVirtualProtect( ( void * ) addr, 4, PAGE_EXECUTE_READWRITE, &dwOldProtect );! F& o" J( u5 U$ E. C* V7 N
lpDDAddr= *((DWORD*)addr);3 c% A. i: Q5 E- }. H; h$ @9 O
lpDD = (struct IDirectDraw7 *)lpDDAddr;
+ n0 h. I- x6 w( ?4 O7 e1 S8 v! _9 Y$ q, Q5 ]2 P$ X8 x
// Enum Surface! {3 l- r1 L, x3 s9 ?+ k! v }% O
mout("now start to enum:\n");
2 q, y: F ~, P1 c! wlpDD->EnumSurfaces( DDENUMSURFACES_DOESEXIST | DDENUMSURFACES_ALL, NULL, NULL, _surfaceEnumCallback_GetPrimary );1 A Z$ _+ i7 o& { G. H
for(int i=0;i<4;i++){
s, T2 X5 c7 M. v5 O) o4 m wsprintf(buff2, "found surface[%d]: %8x\n", i, lpDDS);
; S# m% c- K' g$ J8 g mout(buff2);
8 n$ u9 {) L0 b7 Y1 s8 V}+ h3 y2 {( W7 j- b+ x) c( O
, l3 Y+ S X( p E5 q) _0 Y: ]
$ ?+ L; H* k$ a
--------------------------------------------------------------------------------( p" j6 g. G- }3 I8 B4 k
第6个回答
; R3 G0 H5 {1 R! H帮顶 # i8 d% }6 i6 ?8 `. P
--------------------------------------------------------------------------------0 Q- g* K8 L, v. j; V4 X
第7个回答2 I% X& N, t# ? P: E
在它的backBuffer绘制试试。 2 h. `- P C6 E# \: b& h8 f
--------------------------------------------------------------------------------) t8 I& N# }8 ^" r+ k, v
第8个回答4 A- R" _7 Z5 o9 `3 }$ O, W
backBuffer 无法GetDC(),就无法TextOut 6 y H7 J$ G8 X: m
--------------------------------------------------------------------------------- [' I# y" V" d* ]- G: J
第9个回答
, @8 F) T7 w1 ~backBuffer怎么会无法GetDC呢?那那个程序本身是怎么往上绘东西的啊。你看看是不是其它地方错了。
7 o; ?1 m* k( X0 o6 e) p8 r--------------------------------------------------------------------------------6 `* W7 P1 u5 W9 }% X$ c. y
第10个回答
, X O( e) h S' g不会有错,那个程序是解码MP4视频流数据后,用ddraw加以显示,程序本身用不到GetDC,我用是为了显示文字。 ' |2 ]5 N# N* d3 k. w. a4 ^
--------------------------------------------------------------------------------5 @+ J2 }, o: W& Z9 D
第11个回答
( ?1 y; u6 |' A' `那程序要往上面绘东西,Blt总得支持吧? - s) t% q' H. w5 H. a% J: @: Y" K
你自己建一个Surface,GetDC后TextOut你的文字,然后Blt到那个BackBuffer上去。
$ y5 K; I8 j2 V2 W-------------------------------------------------------------------------------- |