下面这对对话在研究使用directdraw的游戏汉化时可能能用上。
6 D0 v, j0 m. o2 J6 p
0 t. r# s. E$ s, _, e原文
' A+ v5 z: _* V1 r6 q: qhttp://www.qqgb.com/Program/VC/VCJQ/Program_177879.html , v) S; J5 z" Q. j; s: g+ L- e
# y2 H7 p, U8 b- ?( zdirectdraw主表面显示文字问题 前提:已经Hook了ddraw.dll的几个关键API(包括接口的虚函数表),成功获取到了主表面。
3 a/ ? z6 {2 q. s4 @0 U问题:向主表面的HDC TextOut后,文字是显示出来了,但都保持在屏幕的最顶层,其它窗口经过时也会显示文字。
. U1 y2 A# o& P. |4 m9 C9 j为什么没有附在原窗口(用来显示主表面的)中呢? 第1个回答
; F* `; d/ {, _5 _; R6 W居然还有这种事?HDC是ddraw窗口的DC吗?一个DC绘制的图形不是分离的对象,不可能被拆成两部分显示。后台表面也要同时hook绘制。
" V6 K+ x( r- Q) U# s; H5 y--------------------------------------------------------------------------------
! [, }2 v D4 d' k- M. q' |第2个回答. n$ u; [! p+ o9 n+ {: z
HDC 是主表面实例指针-> GetDC()的,不是窗口的HDC。后台表面GetDC()失败,应该不是真正的后台,它不是用Flip进行显示的,而是主表面用Blt绘制另外一个非主表面。
; x' m! S9 Q" _- N9 ~. n2 P--------------------------------------------------------------------------------, `1 l: @- Y, M
第3个回答8 i7 i: J+ z$ }7 Y# v3 k* W3 u
窗口界面的DDraw程序肯定不可能使用Flip了。 ' m; w( W2 b7 L. H; E
主表面上绘制东西出界是常有的事情,首先要设置Clipper,而且在绘制的时候还要自己获取窗口坐标进行坐标变换,这样才能保证绘制在窗口上。 + _0 V# L3 P' S! j1 F# G
--------------------------------------------------------------------------------% s3 z% R: x n) w- x( y
第4个回答8 q$ T9 Q1 K! I, K8 n8 q
我是想在第3方的视频播放器中显示文字,已经Hook了DDraw.dll,得到了主表面实例指针lpddsPrimary,此时主表面已经设置过了Clipper,
& U( \$ E8 ]4 `) _* Y我只是lpddsPrimary-> GetDC(),然后Textout,出现显示的文字和画面分离的情况,文字显示的位置正确,但保持在屏幕的最上端,当有其它窗口
, J0 @/ Z+ ~ N1 y1 i经过时也会显示文字。难道HDC也要设置Clipper,不会吧,真不知道怎么解决?!
3 S d9 N+ a6 t0 ?/ b) z另外是不是可以附加个覆盖页面(overlay),用来显示文字;但覆盖页面GetDC会失败,不能Textout,怎样才能在覆盖页面上显示文字?!
: }' _" C) s" t--------------------------------------------------------------------------------
9 e6 a1 K h: f1 {) C第5个回答
& i4 q6 d' @+ N# D: H, x+ C我也做过这事,,我的方法是注入一个dll,枚举它当前程序里所有的surface,然后分别往枚举出来的surface上textout,看哪个能用,效果最好
$ m$ I, W8 F1 U, J# S! E' [* G6 M6 X$ L* o( n
C/C++ code
* ]. |$ B* K: Y" S) V% ?/ Z3 s--------------------------------------------------------------------------------
( X" @ f/ |: g7 H @1 a. iLPDIRECTDRAWSURFACE7 lpDDSPrimary;//主surface
8 I8 f$ a5 ?4 m4 d6 d8 ^( B. f$ t1 V4 rLPDIRECTDRAWSURFACE7 lpDDS[4];//用来保存枚举出的surface
7 j9 g7 Y \ W6 CDWORD lpDDAddr = 0x00160e50;//lpDD的地址,通过调试很容易得到
) m. X" L7 v9 N" Z/ XLPDIRECTDRAW7 lpDD;
. H; T- }( Q) j, ]! q uDDSURFACEDESC2 ddsd;9 I4 D% H1 D0 E/ ?. R
- c' p$ p8 b1 S* M; p6 F: Q! @' Tint si=0;//surface计数- h# i: v* C6 ]' f- J+ {0 v$ d2 O1 Z. J& b
DDSCAPS2 ddscaps ;: s0 X$ N3 j$ c# Y: a5 F2 H
HRESULT WINAPI _surfaceEnumCallback_GetPrimary( LPDIRECTDRAWSURFACE7 lpDDSurface, LPDDSURFACEDESC2 lpDDSurfaceDesc, LPVOID /*lpContext*/ ) {4 X, S6 q& u) C4 M9 O( [6 B7 \
lpDDS[si] = lpDDSurface;
& |# B0 W3 K/ `7 k' S1 ?8 N0 i si++;3 R- v( c: X# Q, {
wsprintf(buff2, "surface:%8x, width=%d, height=%d, buffCount:%d\n",* v) ^% p% g1 s6 W; o; M9 n
lpDDSurface, lpDDSurfaceDesc->dwWidth,7 l- d; j* K) f; Y& \. |1 ?
lpDDSurfaceDesc->dwHeight,lpDDSurfaceDesc->dwBackBufferCount);; o' s" L+ U) t7 R# @- j% G |
mout(buff2);" o8 j, E# S( U
if( lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE ) { //Primary3 u2 _+ Y4 W" o; |* W" x
lpDDSPrimary = lpDDSurface;
, Q8 x# ^' C$ a& y: ]% g wsprintf(buff2, "primary surface: %8x\n", lpDDSurface);
0 q, ?0 W! |7 i& P mout(buff2);
9 M7 n2 i. a1 X" d; D6 T3 h, d // lpDDSurface->GetSurfaceDesc(&ddsd);0 F r! k4 _# P- I* @
// return DDENUMRET_CANCEL;
/ ^ t2 J' n0 I" A1 ?8 B* @ }
, [$ I* T% O; |. u: e0 K5 b //lpDDSurface->Release();) B; X/ n/ @. s/ I
return DDENUMRET_OK;
V4 A! D# ?5 @( V}
0 L0 J$ l9 A0 C//以上是回调函数,下面是枚举; I: W/ q) M9 i- j# R
// Get lpDD/ |0 E+ d+ V9 Z
DWORD addr=0x00385b2c;
( v5 |! `6 f+ L/ e- v. b% H: kVirtualProtect( ( void * ) addr, 4, PAGE_EXECUTE_READWRITE, &dwOldProtect );
3 t1 i# k e; P( r% L. q# R3 ^% glpDDAddr= *((DWORD*)addr);9 b! H" D0 _: Y2 n8 H4 q L1 W3 t. x- x
lpDD = (struct IDirectDraw7 *)lpDDAddr;
: e/ w. U; P) r1 N' `1 g1 D: J( P& m4 T; X' q5 g& B' I
// Enum Surface
0 }+ n' r$ h* W' M; Kmout("now start to enum:\n");
% v! _' V$ a" W5 s2 vlpDD->EnumSurfaces( DDENUMSURFACES_DOESEXIST | DDENUMSURFACES_ALL, NULL, NULL, _surfaceEnumCallback_GetPrimary );
1 t/ z m- Q$ {% n1 c# O, H; p& Rfor(int i=0;i<4;i++){; C% v% i) W0 i1 [1 w4 L$ z
wsprintf(buff2, "found surface[%d]: %8x\n", i, lpDDS);" G( D$ s8 o! `
mout(buff2);
+ e: {0 u, G2 S. j6 O}( ?$ P; \2 |) d: A. X
$ d6 p9 T! f* v7 F
, V( O* e+ q i
--------------------------------------------------------------------------------9 _% `+ G9 n: J* l
第6个回答8 C# r# w; Q2 r$ H/ ?' ~# ?
帮顶 ; |5 L9 u$ X+ D/ U" l! u
--------------------------------------------------------------------------------
0 \; a' K# S* u: `4 r第7个回答
/ u) [0 _* c. u9 r3 n在它的backBuffer绘制试试。 . M& s9 U0 r# V- j W$ n
--------------------------------------------------------------------------------
: |( {/ l" \8 S! C, v% p T第8个回答+ a% ]# J9 `8 r% J
backBuffer 无法GetDC(),就无法TextOut
0 w- f7 S: w6 x--------------------------------------------------------------------------------. E. ^4 u2 `+ g* j2 u4 I
第9个回答
* @% ?3 C E. W7 V/ a/ ebackBuffer怎么会无法GetDC呢?那那个程序本身是怎么往上绘东西的啊。你看看是不是其它地方错了。
: X X* f9 n M6 E--------------------------------------------------------------------------------6 Z6 [6 l3 l1 R$ Q2 F2 p
第10个回答
& t- k H2 Y& f不会有错,那个程序是解码MP4视频流数据后,用ddraw加以显示,程序本身用不到GetDC,我用是为了显示文字。
. t1 ~1 _% ^! q0 n m--------------------------------------------------------------------------------
9 [6 I, g" w9 y- B/ h0 ~第11个回答
$ K6 X7 n6 g; L那程序要往上面绘东西,Blt总得支持吧? 1 T8 m; k7 T- `7 T* a5 E6 v
你自己建一个Surface,GetDC后TextOut你的文字,然后Blt到那个BackBuffer上去。 $ T$ f+ o3 y6 ?
-------------------------------------------------------------------------------- |