冒险解谜游戏中文网 ChinaAVG
标题:
【图像识别汉化研究】directdraw主表面显示文字疑难
[打印本页]
作者:
shane007
时间:
2009-5-30 09:51
标题:
【图像识别汉化研究】directdraw主表面显示文字疑难
下面这对对话在研究使用directdraw的游戏汉化时可能能用上。
, E; s! ~% }1 y7 E# c. _+ A$ D
. J! P5 L9 |2 i V8 u
原文
# g* I0 w- t" S) E
http://www.qqgb.com/Program/VC/VCJQ/Program_177879.html
$ u+ U4 ?- v3 T# d; I8 _/ w
5 V6 X+ \1 p9 p. M
directdraw主表面显示文字问题 前提:已经Hook了ddraw.dll的几个关键API(包括接口的虚函数表),成功获取到了主表面。
2 d R$ M' v4 ?) w6 I5 E/ a- r
问题:向主表面的HDC TextOut后,文字是显示出来了,但都保持在屏幕的最顶层,其它窗口经过时也会显示文字。
. w& n! h/ P" A/ C u
为什么没有附在原窗口(用来显示主表面的)中呢? 第1个回答
5 ?# K4 }! l1 `# k; ]3 D7 L
居然还有这种事?HDC是ddraw窗口的DC吗?一个DC绘制的图形不是分离的对象,不可能被拆成两部分显示。后台表面也要同时hook绘制。
. l6 Z C6 x4 `8 K
--------------------------------------------------------------------------------
: u% o: U h7 |
第2个回答
$ p$ E" ~: O, N8 w' T/ F
HDC 是主表面实例指针-> GetDC()的,不是窗口的HDC。后台表面GetDC()失败,应该不是真正的后台,它不是用Flip进行显示的,而是主表面用Blt绘制另外一个非主表面。
- j( U7 f+ K, z: b/ H8 {! D
--------------------------------------------------------------------------------
% t! ~' l% i1 K7 n; `9 u
第3个回答
# p# ~0 R5 S. G7 t" V( O7 t5 q
窗口界面的DDraw程序肯定不可能使用Flip了。
: D& M1 w9 `8 r7 R! l
主表面上绘制东西出界是常有的事情,首先要设置Clipper,而且在绘制的时候还要自己获取窗口坐标进行坐标变换,这样才能保证绘制在窗口上。
+ j$ q6 o5 L+ P9 u: l! ~
--------------------------------------------------------------------------------
5 `+ s' P. U1 _# b: L0 R2 O3 B
第4个回答
' A4 `; Q% S' l9 v! J, k! r
我是想在第3方的视频播放器中显示文字,已经Hook了DDraw.dll,得到了主表面实例指针lpddsPrimary,此时主表面已经设置过了Clipper,
: f a1 A9 A8 S. |, j/ d! Q
我只是lpddsPrimary-> GetDC(),然后Textout,出现显示的文字和画面分离的情况,文字显示的位置正确,但保持在屏幕的最上端,当有其它窗口
4 N, v G# K: y7 @: A
经过时也会显示文字。难道HDC也要设置Clipper,不会吧,真不知道怎么解决?!
% @: e2 \7 W. x+ L+ i
另外是不是可以附加个覆盖页面(overlay),用来显示文字;但覆盖页面GetDC会失败,不能Textout,怎样才能在覆盖页面上显示文字?!
9 X5 J+ L) m9 P% I$ k1 _( V
--------------------------------------------------------------------------------
! U- ^ I* @3 h2 o
第5个回答
7 O* N& ^8 Q0 G
我也做过这事,,我的方法是注入一个dll,枚举它当前程序里所有的surface,然后分别往枚举出来的surface上textout,看哪个能用,效果最好
. O# q" {! Q6 K6 G n; N
I W( T, H. @: ^
C/C++ code
N2 B5 }# _$ s( ^8 d8 \. b
--------------------------------------------------------------------------------
4 o* f9 C3 R7 c/ ~% y' F
LPDIRECTDRAWSURFACE7 lpDDSPrimary;//主surface
& N! V8 o/ B6 Y ~/ t9 ~' m& |* Q
LPDIRECTDRAWSURFACE7 lpDDS[4];//用来保存枚举出的surface
& }2 J( {) W% `
DWORD lpDDAddr = 0x00160e50;//lpDD的地址,通过调试很容易得到
5 [' U0 f8 h$ B+ b+ _
LPDIRECTDRAW7 lpDD;
- o( H* c9 m" Y% A! r$ Z) u" l
DDSURFACEDESC2 ddsd;
- K0 x- U! H b+ K
& m V2 h, D! G$ H
int si=0;//surface计数
& c5 h& v# X" X" m: ? q: q! {
DDSCAPS2 ddscaps ;
, w. ^+ V, h; t9 M' A* K& U5 o
HRESULT WINAPI _surfaceEnumCallback_GetPrimary( LPDIRECTDRAWSURFACE7 lpDDSurface, LPDDSURFACEDESC2 lpDDSurfaceDesc, LPVOID /*lpContext*/ ) {
6 q; s0 K* S* p7 w% b
lpDDS[si] = lpDDSurface;
' a5 X4 W) j. B W( s
si++;
# @: R p7 J( A) i5 o1 n. n
wsprintf(buff2, "surface:%8x, width=%d, height=%d, buffCount:%d\n",
& e5 x0 |) Q! c1 v l. I( `
lpDDSurface, lpDDSurfaceDesc->dwWidth,
( j$ k/ q6 [2 [- C" m8 S1 D
lpDDSurfaceDesc->dwHeight,lpDDSurfaceDesc->dwBackBufferCount);
1 G+ t) D# Y F
mout(buff2);
, `* H: l* y6 ]3 H
if( lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE ) { //Primary
5 J, R) x8 w, B; o0 v
lpDDSPrimary = lpDDSurface;
3 W2 P9 u( k( ^1 q: Q, Z* j8 ]
wsprintf(buff2, "primary surface: %8x\n", lpDDSurface);
/ y* m2 w+ Q/ v6 R
mout(buff2);
2 e' q& Y( y8 N/ W( J% u
// lpDDSurface->GetSurfaceDesc(&ddsd);
E+ D; Z" g2 J( x: O
// return DDENUMRET_CANCEL;
# r2 o- Y- B- e. x7 S! t9 t* P9 E
}
* u+ Y' D, e6 s& q* c! w: B+ U3 |% y
//lpDDSurface->Release();
: r4 y" c$ }" v# V7 h9 Z7 f8 N2 V
return DDENUMRET_OK;
' \2 S2 R- @5 u2 d+ \+ R9 @) M
}
. [2 r/ L" b+ q9 c: m% K9 y
//以上是回调函数,下面是枚举
8 g0 L" `* [; o7 o6 ~0 [0 |
// Get lpDD
: \) [) s; E# }$ ^- E
DWORD addr=0x00385b2c;
1 q* ~& w: \; x/ {( o: `6 r
VirtualProtect( ( void * ) addr, 4, PAGE_EXECUTE_READWRITE, &dwOldProtect );
' W1 q* f- o/ D* b1 t
lpDDAddr= *((DWORD*)addr);
4 M, I& T" t' t) _
lpDD = (struct IDirectDraw7 *)lpDDAddr;
* N g: N& X m' V
, g$ b& ]/ j' Y* Q6 F: i! y
// Enum Surface
* S H' Q& E! U3 \: N1 x3 A
mout("now start to enum:\n");
' G- ]$ M. I5 D$ g
lpDD->EnumSurfaces( DDENUMSURFACES_DOESEXIST | DDENUMSURFACES_ALL, NULL, NULL, _surfaceEnumCallback_GetPrimary );
; C7 t' B$ n! t' u6 G$ M
for(int i=0;i<4;i++){
* H4 e( e% C8 t+ v6 N
wsprintf(buff2, "found surface[%d]: %8x\n", i, lpDDS
);
( I5 u6 M, n* |0 J, Q) i
mout(buff2);
1 I( I& ^! v0 p U% [2 z, E
}
, o }4 Z( @) Q2 T5 f4 [2 K
0 [5 E- v1 {8 O
8 o" I' g4 c4 i; _2 d/ e
--------------------------------------------------------------------------------
# r# k0 z; p- a) P" i( v
第6个回答
: q4 J2 u; V0 G t7 @3 b
帮顶
$ a9 W& }6 } W
--------------------------------------------------------------------------------
- x+ K% l g8 F T8 B. W7 q2 M! Y
第7个回答
' t6 n+ Z2 o6 J p
在它的backBuffer绘制试试。
. }' ?& Y8 g! ~8 u; j( Q
--------------------------------------------------------------------------------
$ C; [' n; P4 w3 a; t: q* P
第8个回答
. h# f* d' S+ n( U" a- D5 ]/ x
backBuffer 无法GetDC(),就无法TextOut
& n* p% E0 ~) h2 ?* J# t+ ~) Z
--------------------------------------------------------------------------------
; \ P: u- X( D6 n
第9个回答
}: R1 n1 L9 v7 X" s7 {+ \
backBuffer怎么会无法GetDC呢?那那个程序本身是怎么往上绘东西的啊。你看看是不是其它地方错了。
* G% Z" l& M/ K# m& f) h7 U- y
--------------------------------------------------------------------------------
7 Y# P1 v4 \ T' w
第10个回答
3 R9 @, T' e- S6 ~
不会有错,那个程序是解码MP4视频流数据后,用ddraw加以显示,程序本身用不到GetDC,我用是为了显示文字。
5 l9 n7 z d: H! g. f$ g G t f
--------------------------------------------------------------------------------
" F+ \; |; \# @8 \5 G
第11个回答
! ~. d7 U Z; s$ T7 G- B
那程序要往上面绘东西,Blt总得支持吧?
1 f" K+ t8 }, {
你自己建一个Surface,GetDC后TextOut你的文字,然后Blt到那个BackBuffer上去。
]% ~6 f8 n1 [# \/ j3 B F* K* R
--------------------------------------------------------------------------------
欢迎光临 冒险解谜游戏中文网 ChinaAVG (https://chinaavg.com/)
Powered by Discuz! X3.2