下面这对对话在研究使用directdraw的游戏汉化时可能能用上。
# ]1 N# O0 z0 P5 l/ W5 _& O7 @. ^3 z2 {; z9 [
原文# W0 O: o0 e$ r, J9 `; M' }6 C+ i1 g
http://www.qqgb.com/Program/VC/VCJQ/Program_177879.html
9 x; v. x3 c% x. q: y$ u4 c- f
/ e: j3 H/ i `- A- a- z qdirectdraw主表面显示文字问题 前提:已经Hook了ddraw.dll的几个关键API(包括接口的虚函数表),成功获取到了主表面。
7 L! s j2 o7 R" u% O问题:向主表面的HDC TextOut后,文字是显示出来了,但都保持在屏幕的最顶层,其它窗口经过时也会显示文字。 ; X. y# T6 ]/ D a' `6 n
为什么没有附在原窗口(用来显示主表面的)中呢? 第1个回答7 q/ t' E2 W3 ?0 l
居然还有这种事?HDC是ddraw窗口的DC吗?一个DC绘制的图形不是分离的对象,不可能被拆成两部分显示。后台表面也要同时hook绘制。 / c* E9 o4 n, U8 F& u
--------------------------------------------------------------------------------
$ a& m( o; w# Q0 Y h3 s! H第2个回答
! I5 I: z9 M+ R. `0 XHDC 是主表面实例指针-> GetDC()的,不是窗口的HDC。后台表面GetDC()失败,应该不是真正的后台,它不是用Flip进行显示的,而是主表面用Blt绘制另外一个非主表面。
9 `% A# m$ ` X, [--------------------------------------------------------------------------------4 u/ ]9 ]3 K9 R
第3个回答
& n+ ], h2 W6 k( M; N窗口界面的DDraw程序肯定不可能使用Flip了。
4 [# @9 O, |+ G7 q主表面上绘制东西出界是常有的事情,首先要设置Clipper,而且在绘制的时候还要自己获取窗口坐标进行坐标变换,这样才能保证绘制在窗口上。
B. g4 p/ D5 W--------------------------------------------------------------------------------
: n7 |3 q; m& x! x/ c- G2 a9 f第4个回答, k2 F, F( S1 g3 J: e
我是想在第3方的视频播放器中显示文字,已经Hook了DDraw.dll,得到了主表面实例指针lpddsPrimary,此时主表面已经设置过了Clipper,
1 C: R+ ^* s, Y: D我只是lpddsPrimary-> GetDC(),然后Textout,出现显示的文字和画面分离的情况,文字显示的位置正确,但保持在屏幕的最上端,当有其它窗口
0 H6 G' v, t9 S7 ?2 X9 M Z2 U经过时也会显示文字。难道HDC也要设置Clipper,不会吧,真不知道怎么解决?!
: s0 K: ~; _/ T3 O- p8 d另外是不是可以附加个覆盖页面(overlay),用来显示文字;但覆盖页面GetDC会失败,不能Textout,怎样才能在覆盖页面上显示文字?! + i+ f/ U; K4 O% b- q7 ^
--------------------------------------------------------------------------------
% Y- e3 h9 ?/ y1 B9 J5 r第5个回答
8 ~# R4 Y, n; N0 X; \# k% V) P我也做过这事,,我的方法是注入一个dll,枚举它当前程序里所有的surface,然后分别往枚举出来的surface上textout,看哪个能用,效果最好
/ q) B& \3 R& M& M4 E2 q% g- w
4 c; ]% P1 o3 e: P! tC/C++ code* F3 B# T4 o* a k* K8 [, [2 y
--------------------------------------------------------------------------------+ b* B- n/ L6 p2 P3 O
LPDIRECTDRAWSURFACE7 lpDDSPrimary;//主surface
/ T8 ]: ?& m$ X" S6 E( F- ILPDIRECTDRAWSURFACE7 lpDDS[4];//用来保存枚举出的surface
; c6 f# H$ D/ j) eDWORD lpDDAddr = 0x00160e50;//lpDD的地址,通过调试很容易得到
- ?" E/ `0 d6 [5 HLPDIRECTDRAW7 lpDD;
2 }; y3 Y+ ]8 }0 g2 G% V+ u3 G3 v0 eDDSURFACEDESC2 ddsd;* w& E0 M$ _! z) ^+ Y4 v
: i+ M3 E: Z& C5 S* m0 y, N
int si=0;//surface计数 L5 Z7 T' Z: g$ f. k* z: C! |6 I
DDSCAPS2 ddscaps ;8 A2 L0 S, d5 S3 ~0 t
HRESULT WINAPI _surfaceEnumCallback_GetPrimary( LPDIRECTDRAWSURFACE7 lpDDSurface, LPDDSURFACEDESC2 lpDDSurfaceDesc, LPVOID /*lpContext*/ ) {3 d7 h# Z% K* f6 C; i: |
lpDDS[si] = lpDDSurface;
- K* r, [' @& S0 U) V/ p6 W2 l0 K) |6 X% A si++;" V: F# o1 F1 O2 C' y9 ]4 a
wsprintf(buff2, "surface:%8x, width=%d, height=%d, buffCount:%d\n",
1 c3 k) T% o5 |! C lpDDSurface, lpDDSurfaceDesc->dwWidth,
1 Z# i) M1 | m! y4 r lpDDSurfaceDesc->dwHeight,lpDDSurfaceDesc->dwBackBufferCount);( B7 b, ^4 p. p9 p! `, X4 Z
mout(buff2);- T8 `& v+ o9 F$ b. F
if( lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE ) { //Primary( Z# i f& S+ w# R) B2 d# C! \2 C
lpDDSPrimary = lpDDSurface;4 L( K% U3 u$ Y5 R
wsprintf(buff2, "primary surface: %8x\n", lpDDSurface);
% \% i; Y" `6 \* ] mout(buff2);
0 J: z" b# W1 w; e8 K6 C$ F // lpDDSurface->GetSurfaceDesc(&ddsd);
0 }/ G3 }/ x2 n; I* d // return DDENUMRET_CANCEL;6 J0 c5 O2 O7 r; k9 `- R2 P
} % `+ b& o+ ^9 U; }* Q4 J; n
//lpDDSurface->Release();, r, ~" f6 @, K, g9 C" P2 u
return DDENUMRET_OK;/ O( f4 y9 ?& A, Y Z! q/ _ t% _8 C
}1 h5 E; _) n! r! X Y r6 v
//以上是回调函数,下面是枚举2 g* v! h* d7 g9 p1 @! s; q
// Get lpDD
~; W4 U; E0 a5 T4 v3 t8 }; VDWORD addr=0x00385b2c;
) J. K1 u9 m. i2 zVirtualProtect( ( void * ) addr, 4, PAGE_EXECUTE_READWRITE, &dwOldProtect );
3 T1 \$ \# H- K: LlpDDAddr= *((DWORD*)addr);
- [# O k, n. Z( o3 _( m B6 PlpDD = (struct IDirectDraw7 *)lpDDAddr;
3 }- i& }" ^$ a" c. p$ b& d4 J, {
( j$ a4 t6 |9 u" V7 J6 g// Enum Surface
' I; ]1 q' ]+ I2 N3 R" emout("now start to enum:\n");
$ _* j2 ]: _9 V- H9 k$ `2 VlpDD->EnumSurfaces( DDENUMSURFACES_DOESEXIST | DDENUMSURFACES_ALL, NULL, NULL, _surfaceEnumCallback_GetPrimary );4 V, R" k& [1 L/ E4 K$ l! V& W/ E
for(int i=0;i<4;i++){! A9 Z+ J0 @3 y+ G, t9 j% ~
wsprintf(buff2, "found surface[%d]: %8x\n", i, lpDDS);
$ ], N1 |3 w6 ?% l4 O, N! \& T! F mout(buff2);
+ J/ a2 \ Z% _) D% {}7 e! W W7 q v; i
5 W5 _' H% s+ F. v/ a+ l; h/ d2 _) K- a
--------------------------------------------------------------------------------8 q. B0 H u# \- |: T7 m5 k% o, v
第6个回答% z8 m& {( _- }8 W# s9 X# T
帮顶 ; M9 D& V! o- \$ I6 r J- v
--------------------------------------------------------------------------------
5 M% ^, f# n. Y, |" v5 ]' `第7个回答3 J. L3 l- ]: n4 f- t
在它的backBuffer绘制试试。
2 J* f0 @" H! h" G--------------------------------------------------------------------------------- A. V" ^+ m: [2 _. c
第8个回答5 r: q+ ^# x" w; @' H" J+ y) ?: I
backBuffer 无法GetDC(),就无法TextOut * X- _* f% T" H, t/ d2 v5 O
--------------------------------------------------------------------------------
$ o4 B; E& p6 w1 `# K第9个回答
4 u: K8 ~0 y# hbackBuffer怎么会无法GetDC呢?那那个程序本身是怎么往上绘东西的啊。你看看是不是其它地方错了。 ) R4 M) J9 X5 p+ j4 q
--------------------------------------------------------------------------------
6 q4 O2 t5 C3 z第10个回答7 p0 d$ x: c2 `/ z7 Q& [$ ~
不会有错,那个程序是解码MP4视频流数据后,用ddraw加以显示,程序本身用不到GetDC,我用是为了显示文字。 / h' \' z( `4 L3 K
--------------------------------------------------------------------------------
+ c6 u) \, Y2 G5 K, b第11个回答
6 n% b5 }( p) B" V那程序要往上面绘东西,Blt总得支持吧?
9 u3 S1 E% F: c! L4 B你自己建一个Surface,GetDC后TextOut你的文字,然后Blt到那个BackBuffer上去。 , D! K. W/ N; w! Z- @
-------------------------------------------------------------------------------- |