下面这对对话在研究使用directdraw的游戏汉化时可能能用上。
5 L0 V* C* T5 j6 X
* h, t O* z8 c$ K, G( C5 e原文, L4 ]2 S8 r* U# r1 @9 M8 Y3 k, ?
http://www.qqgb.com/Program/VC/VCJQ/Program_177879.html
2 o( x3 u) z! b6 d
7 j! e) |. W5 G/ j* Cdirectdraw主表面显示文字问题 前提:已经Hook了ddraw.dll的几个关键API(包括接口的虚函数表),成功获取到了主表面。
d1 K- r: u" ?/ Q, m* Y问题:向主表面的HDC TextOut后,文字是显示出来了,但都保持在屏幕的最顶层,其它窗口经过时也会显示文字。 8 h4 e/ J$ _4 x/ V6 t- W& S1 c: W
为什么没有附在原窗口(用来显示主表面的)中呢? 第1个回答
2 H7 x$ ?2 }, E; J居然还有这种事?HDC是ddraw窗口的DC吗?一个DC绘制的图形不是分离的对象,不可能被拆成两部分显示。后台表面也要同时hook绘制。
) s' V: V* J/ u2 B2 F- {0 m) e--------------------------------------------------------------------------------) D2 p+ ], |1 Q: n+ c p
第2个回答
3 C+ D. h( B8 i) Y2 THDC 是主表面实例指针-> GetDC()的,不是窗口的HDC。后台表面GetDC()失败,应该不是真正的后台,它不是用Flip进行显示的,而是主表面用Blt绘制另外一个非主表面。 ' Y9 U$ ^8 ^+ G
--------------------------------------------------------------------------------
, D, [+ M" m3 c& i! N% S第3个回答
& O. r, |0 q k窗口界面的DDraw程序肯定不可能使用Flip了。
+ Q9 U3 P1 U4 W( Y- |/ @) N- M主表面上绘制东西出界是常有的事情,首先要设置Clipper,而且在绘制的时候还要自己获取窗口坐标进行坐标变换,这样才能保证绘制在窗口上。
4 @0 W) L, ?# ?. m' e. c6 F--------------------------------------------------------------------------------( |7 V) u8 M$ x6 S4 f
第4个回答$ w& v- j5 @( F$ K/ Z
我是想在第3方的视频播放器中显示文字,已经Hook了DDraw.dll,得到了主表面实例指针lpddsPrimary,此时主表面已经设置过了Clipper,
, q$ C: ]. |: Z& [8 D4 N我只是lpddsPrimary-> GetDC(),然后Textout,出现显示的文字和画面分离的情况,文字显示的位置正确,但保持在屏幕的最上端,当有其它窗口 9 P& `2 ]: R0 P
经过时也会显示文字。难道HDC也要设置Clipper,不会吧,真不知道怎么解决?!
2 q1 O) q3 K2 u' N9 y. t另外是不是可以附加个覆盖页面(overlay),用来显示文字;但覆盖页面GetDC会失败,不能Textout,怎样才能在覆盖页面上显示文字?! % S& g8 y% ?1 g3 V! ~
--------------------------------------------------------------------------------' V# ^8 d" C2 W* \) S. ]
第5个回答" H' ?( }' s* h$ d
我也做过这事,,我的方法是注入一个dll,枚举它当前程序里所有的surface,然后分别往枚举出来的surface上textout,看哪个能用,效果最好
a9 D) H0 }& P0 u3 g% M
) q+ c% V: ~2 pC/C++ code
$ v+ R3 s6 d+ _( Q--------------------------------------------------------------------------------( G2 d0 s! W$ O9 C P4 D- j5 f
LPDIRECTDRAWSURFACE7 lpDDSPrimary;//主surface+ `# x% {/ `/ K' X* x; ^
LPDIRECTDRAWSURFACE7 lpDDS[4];//用来保存枚举出的surface
% u3 i( F7 H/ P7 zDWORD lpDDAddr = 0x00160e50;//lpDD的地址,通过调试很容易得到7 j4 S9 C4 C$ j' @$ H" D* A
LPDIRECTDRAW7 lpDD;0 ~7 X' ?% L+ y8 z4 N& Q
DDSURFACEDESC2 ddsd;/ w/ c( ~6 i9 S
: D% }/ b" u9 W) J7 z3 ~2 K* p6 X7 @
int si=0;//surface计数
5 p$ `8 A6 a: ]: q8 X8 O; dDDSCAPS2 ddscaps ;
7 _8 U# G+ E, e2 A" N6 DHRESULT WINAPI _surfaceEnumCallback_GetPrimary( LPDIRECTDRAWSURFACE7 lpDDSurface, LPDDSURFACEDESC2 lpDDSurfaceDesc, LPVOID /*lpContext*/ ) {3 q# ^" K$ M6 ^+ @
lpDDS[si] = lpDDSurface;
3 p6 j) `6 C6 t) }0 Y$ d5 G si++;& i( e9 S! P5 b0 ~3 z7 _) x W& ~
wsprintf(buff2, "surface:%8x, width=%d, height=%d, buffCount:%d\n",! Q' R/ Q* v) D
lpDDSurface, lpDDSurfaceDesc->dwWidth,2 Z6 X8 J( J6 |, \, ?" N
lpDDSurfaceDesc->dwHeight,lpDDSurfaceDesc->dwBackBufferCount);- b6 K4 }/ A' c$ \
mout(buff2);3 ^9 l3 g6 Y7 X3 U% D3 z+ J
if( lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE ) { //Primary
) w- K! `/ c/ C: H. { lpDDSPrimary = lpDDSurface;* j" ]% K# t8 k+ A# }
wsprintf(buff2, "primary surface: %8x\n", lpDDSurface);3 D) `5 R' f' d6 _6 O7 V" q' D
mout(buff2);: z. N* K: `# j
// lpDDSurface->GetSurfaceDesc(&ddsd);0 O# P# W4 Q i6 O$ R' \
// return DDENUMRET_CANCEL;7 c$ C- h3 H& f' F; [
} % L) s, \4 s6 [( @' n+ x, ]
//lpDDSurface->Release();
" @! Z8 m) t8 Q# a8 ]3 I9 |$ h return DDENUMRET_OK;4 {, u% A' ~0 m: N% m6 t2 w
}5 R- e" r8 ]; @- J& O
//以上是回调函数,下面是枚举
* C2 N' `& I/ @9 O// Get lpDD
% R6 ^! I- U& I9 CDWORD addr=0x00385b2c;
% x$ o8 m; A4 T8 T8 KVirtualProtect( ( void * ) addr, 4, PAGE_EXECUTE_READWRITE, &dwOldProtect );
) g/ D4 R! K( |; ElpDDAddr= *((DWORD*)addr);
) \) L2 [& ]8 w, L0 _* PlpDD = (struct IDirectDraw7 *)lpDDAddr;
) v7 O4 K6 Q( \4 F2 r Y, B- T+ a6 r( S/ @; C. P+ T
// Enum Surface$ H3 D6 s0 [# A% @' ?, D& s
mout("now start to enum:\n");5 l, a {; O0 L, ?: E3 b
lpDD->EnumSurfaces( DDENUMSURFACES_DOESEXIST | DDENUMSURFACES_ALL, NULL, NULL, _surfaceEnumCallback_GetPrimary );% {* o: k: p4 ^3 r
for(int i=0;i<4;i++){
- M, G. |: Y& [% Q! M" g wsprintf(buff2, "found surface[%d]: %8x\n", i, lpDDS);# X6 }" W7 ^, p+ k+ y( x& `
mout(buff2);
* |: D: u; w3 L+ w}
" H9 ]: [' |- Q
( `9 t9 c# O* {, t8 o
6 `5 x g9 c2 r6 A2 ]3 T--------------------------------------------------------------------------------3 e, ^/ d& v; h9 J i: j0 l. v9 D
第6个回答
9 W1 T; L& l) c- A8 I% u帮顶
5 q3 V) z7 k$ F0 j5 U$ U--------------------------------------------------------------------------------! B* g/ w( k D7 l2 h% z8 w
第7个回答 a& E( k0 ?3 p9 F
在它的backBuffer绘制试试。
) J' l9 O' V# I0 ]--------------------------------------------------------------------------------9 o& |9 v Y; v1 [
第8个回答
5 P; I9 e3 s w: u6 W6 [9 FbackBuffer 无法GetDC(),就无法TextOut 9 I3 ]/ {$ a: o$ O1 c4 N6 X
--------------------------------------------------------------------------------
3 P2 v3 ]2 x; f第9个回答
0 P$ ~; A$ d8 M3 A8 w3 @8 {' n' AbackBuffer怎么会无法GetDC呢?那那个程序本身是怎么往上绘东西的啊。你看看是不是其它地方错了。 - l' R* M. o* [/ X0 I1 W
--------------------------------------------------------------------------------0 N9 M [$ b3 a8 ]! b
第10个回答 V! Y T6 T* L. E# T
不会有错,那个程序是解码MP4视频流数据后,用ddraw加以显示,程序本身用不到GetDC,我用是为了显示文字。 5 V9 ~% U/ _" K* R6 K
--------------------------------------------------------------------------------
6 Z+ g: F w7 N g- I第11个回答! i7 ]5 q+ k. j, n* V2 H; T
那程序要往上面绘东西,Blt总得支持吧?
3 O, V9 A4 ]) R5 x! P8 W: A# q你自己建一个Surface,GetDC后TextOut你的文字,然后Blt到那个BackBuffer上去。
* D+ C& Q7 E& h-------------------------------------------------------------------------------- |