下面这对对话在研究使用directdraw的游戏汉化时可能能用上。
3 r9 o: ~ v' v L, t6 O; D4 G1 F" d7 V1 U- L" Q1 i1 d
原文" W( \1 |) i$ m
http://www.qqgb.com/Program/VC/VCJQ/Program_177879.html
; V3 H* p) T, }4 W) p/ b
* ^) |2 V& m) x/ mdirectdraw主表面显示文字问题 前提:已经Hook了ddraw.dll的几个关键API(包括接口的虚函数表),成功获取到了主表面。 7 o: H A- d0 W D5 S% ~, o
问题:向主表面的HDC TextOut后,文字是显示出来了,但都保持在屏幕的最顶层,其它窗口经过时也会显示文字。
1 h$ r# N# N/ ^( K+ l/ @为什么没有附在原窗口(用来显示主表面的)中呢? 第1个回答
: w: |* _) I$ u% @居然还有这种事?HDC是ddraw窗口的DC吗?一个DC绘制的图形不是分离的对象,不可能被拆成两部分显示。后台表面也要同时hook绘制。 % u \/ S q/ V" C: \( k
--------------------------------------------------------------------------------6 L% ~( ~1 f# ]/ n' w6 W7 c' P
第2个回答
* T( \" }1 a9 ^) ~7 p8 ?& DHDC 是主表面实例指针-> GetDC()的,不是窗口的HDC。后台表面GetDC()失败,应该不是真正的后台,它不是用Flip进行显示的,而是主表面用Blt绘制另外一个非主表面。
i9 r0 x( z/ I+ N& w--------------------------------------------------------------------------------
8 n, t5 W: E5 O# A* M0 i; ^第3个回答
/ f }7 e' L' r窗口界面的DDraw程序肯定不可能使用Flip了。
& S! N" k0 O6 c! i) M主表面上绘制东西出界是常有的事情,首先要设置Clipper,而且在绘制的时候还要自己获取窗口坐标进行坐标变换,这样才能保证绘制在窗口上。
0 M) ]2 ?: B# F" \; J( T3 {+ O--------------------------------------------------------------------------------
8 ]6 O1 N, V7 \ Z4 h第4个回答6 r" I7 a( F# {/ y# I1 m$ r
我是想在第3方的视频播放器中显示文字,已经Hook了DDraw.dll,得到了主表面实例指针lpddsPrimary,此时主表面已经设置过了Clipper, K8 m' G, b( k* d9 z
我只是lpddsPrimary-> GetDC(),然后Textout,出现显示的文字和画面分离的情况,文字显示的位置正确,但保持在屏幕的最上端,当有其它窗口 T/ G1 {# n7 X0 ~3 ?
经过时也会显示文字。难道HDC也要设置Clipper,不会吧,真不知道怎么解决?!
6 y) T) V3 M* H9 j- m# s另外是不是可以附加个覆盖页面(overlay),用来显示文字;但覆盖页面GetDC会失败,不能Textout,怎样才能在覆盖页面上显示文字?! , U: f2 m5 I p' {' ]' v
--------------------------------------------------------------------------------
' o6 `& S* t! T0 B: c+ }第5个回答
0 u' m* _7 q' x我也做过这事,,我的方法是注入一个dll,枚举它当前程序里所有的surface,然后分别往枚举出来的surface上textout,看哪个能用,效果最好 " q: G2 k. x$ q" k$ e) [9 Z
% v' v0 Q$ t2 u1 e6 m5 ^ M) @C/C++ code8 s% _$ o8 k, L7 r: k: `
--------------------------------------------------------------------------------. X2 e0 Y9 m- h
LPDIRECTDRAWSURFACE7 lpDDSPrimary;//主surface
$ W d7 y! i$ N6 ]) T T7 c8 [" ZLPDIRECTDRAWSURFACE7 lpDDS[4];//用来保存枚举出的surface
, Q7 H, i' ~- h4 W& v% Z/ pDWORD lpDDAddr = 0x00160e50;//lpDD的地址,通过调试很容易得到, G) \; q/ Y# f7 B4 e- F) _
LPDIRECTDRAW7 lpDD;! V* r: i: ~% E( m+ `+ E8 b, V
DDSURFACEDESC2 ddsd;& \5 ]! \) v& [3 A$ K# p
' F1 w, b9 q) K; S
int si=0;//surface计数& r/ w- ^8 q5 B* R, d/ ^' Z
DDSCAPS2 ddscaps ;; h, a! U2 J; {8 b- w2 C* t, j3 Z
HRESULT WINAPI _surfaceEnumCallback_GetPrimary( LPDIRECTDRAWSURFACE7 lpDDSurface, LPDDSURFACEDESC2 lpDDSurfaceDesc, LPVOID /*lpContext*/ ) {$ A- q) _# H1 e
lpDDS[si] = lpDDSurface;0 U e- ?3 C9 a2 r6 v8 w5 h
si++;3 o5 Y* A$ I( T6 a
wsprintf(buff2, "surface:%8x, width=%d, height=%d, buffCount:%d\n",5 x8 W( ~3 y- H
lpDDSurface, lpDDSurfaceDesc->dwWidth,
" v+ G0 X+ _2 T8 Y lpDDSurfaceDesc->dwHeight,lpDDSurfaceDesc->dwBackBufferCount);4 n3 ?: L" z6 m. K: G7 g
mout(buff2);( d6 Q7 j* Y* v: a6 o* |
if( lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE ) { //Primary
* t* V4 J% U3 N- y- ]0 S8 ]! E lpDDSPrimary = lpDDSurface;
' W$ P; R* L M& Y wsprintf(buff2, "primary surface: %8x\n", lpDDSurface);
5 s$ P$ |( p/ G' a mout(buff2);* {, y q- ^1 A! c. r0 o
// lpDDSurface->GetSurfaceDesc(&ddsd);) |' h1 W1 [& B$ H$ L8 T% F
// return DDENUMRET_CANCEL;
6 l; A, K4 s' v } 4 }8 t( S- R/ |" K3 v
//lpDDSurface->Release();3 v7 W5 B: q7 Y1 I {
return DDENUMRET_OK;- \1 A) Z2 l) K
}: w7 E* l; @9 V* L
//以上是回调函数,下面是枚举
0 w2 A" A4 V( y// Get lpDD
/ P( r+ L7 w8 w# UDWORD addr=0x00385b2c;
, s- S; A1 ?8 P8 \. k- C) k6 HVirtualProtect( ( void * ) addr, 4, PAGE_EXECUTE_READWRITE, &dwOldProtect );/ Q# b0 a$ ^+ M
lpDDAddr= *((DWORD*)addr);
]" {% [9 `7 [( w9 v) I$ zlpDD = (struct IDirectDraw7 *)lpDDAddr;
0 r3 J; V5 F* F" U: Q
: W/ }+ M! Z+ V O8 m- r' [6 F// Enum Surface" O1 E/ K( D; P/ [6 }+ U$ k
mout("now start to enum:\n");) r; v7 Y$ x9 b
lpDD->EnumSurfaces( DDENUMSURFACES_DOESEXIST | DDENUMSURFACES_ALL, NULL, NULL, _surfaceEnumCallback_GetPrimary );% h6 c" {( g1 T/ B" _! M4 x& C- Z
for(int i=0;i<4;i++){3 v1 s2 l a! C; z
wsprintf(buff2, "found surface[%d]: %8x\n", i, lpDDS);
! ]- w. o6 w* F7 W7 B, d mout(buff2);# I6 D, y( d4 x( N/ V
}4 \5 N, o. r) z
0 v' y8 S b. {. L, T
' ^+ M7 h. x. E--------------------------------------------------------------------------------, t; v+ ^9 ^8 H3 t: f! Q% s
第6个回答
- n/ N7 d! y5 U T) Z- k( }8 _帮顶 - @$ }, _- A( ^
--------------------------------------------------------------------------------5 k% W; t" i$ C8 O
第7个回答
* @6 `+ I; T- W5 ~, C在它的backBuffer绘制试试。 * w7 r4 u+ E8 z) G/ V; L! {( t# Z( h4 T
--------------------------------------------------------------------------------
4 }0 w( A7 Q2 G4 r {2 c第8个回答
1 _' x& A) H5 n: p, h- T9 kbackBuffer 无法GetDC(),就无法TextOut
& B- h) y' r' W8 T-------------------------------------------------------------------------------- d2 d7 U, c" J/ p' ^9 G) c
第9个回答' m5 r& [) m* @2 U- K
backBuffer怎么会无法GetDC呢?那那个程序本身是怎么往上绘东西的啊。你看看是不是其它地方错了。 8 e( h. g( |+ Y9 j9 g) e
--------------------------------------------------------------------------------
* s. ]2 R+ w) ^& Y+ h, V$ Y第10个回答
8 ]) Q, C, i: v; x0 P; C. k不会有错,那个程序是解码MP4视频流数据后,用ddraw加以显示,程序本身用不到GetDC,我用是为了显示文字。
9 Q, B& g7 Q- o, u. @+ v( q--------------------------------------------------------------------------------& B: V( p& o; r3 G/ n. X
第11个回答
B# c* R; }) {% o: P那程序要往上面绘东西,Blt总得支持吧? 6 N& f0 a- W$ ]" u# j% o$ Y
你自己建一个Surface,GetDC后TextOut你的文字,然后Blt到那个BackBuffer上去。 % i% U& z1 y, m+ P5 ]
-------------------------------------------------------------------------------- |