前提:已经Hook了ddraw.dll的几个关键API(包括接口的虚函数表),成功获取到了主表面。
问题:向主表面的HDC TextOut后,文字是显示出来了,但都保持在屏幕的最顶层,其它窗口经过时也会显示文字。
为什么没有附在原窗口(用来显示主表面的)中呢?

解决方案 »

  1.   

    居然还有这种事?HDC是ddraw窗口的DC吗?一个DC绘制的图形不是分离的对象,不可能被拆成两部分显示。后台表面也要同时hook绘制。
      

  2.   

    HDC 是主表面实例指针->GetDC()的,不是窗口的HDC。后台表面GetDC()失败,应该不是真正的后台,它不是用Flip进行显示的,而是主表面用Blt绘制另外一个非主表面。
      

  3.   

    窗口界面的DDraw程序肯定不可能使用Flip了。主表面上绘制东西出界是常有的事情,首先要设置Clipper,而且在绘制的时候还要自己获取窗口坐标进行坐标变换,这样才能保证绘制在窗口上。
      

  4.   

    我是想在第3方的视频播放器中显示文字,已经Hook了DDraw.dll,得到了主表面实例指针lpddsPrimary,此时主表面已经设置过了Clipper,
    我只是lpddsPrimary->GetDC(),然后Textout,出现显示的文字和画面分离的情况,文字显示的位置正确,但保持在屏幕的最上端,当有其它窗口
    经过时也会显示文字。难道HDC也要设置Clipper,不会吧,真不知道怎么解决?!另外是不是可以附加个覆盖页面(overlay),用来显示文字;但覆盖页面GetDC会失败,不能Textout,怎样才能在覆盖页面上显示文字?!
      

  5.   

    我也做过这事,,我的方法是注入一个dll,枚举它当前程序里所有的surface,然后分别往枚举出来的surface上textout,看哪个能用,效果最好
    LPDIRECTDRAWSURFACE7 lpDDSPrimary;//主surface
    LPDIRECTDRAWSURFACE7  lpDDS[4];//用来保存枚举出的surface
    DWORD lpDDAddr = 0x00160e50;//lpDD的地址,通过调试很容易得到
    LPDIRECTDRAW7 lpDD;
    DDSURFACEDESC2 ddsd;int si=0;//surface计数
    DDSCAPS2 ddscaps ;
    HRESULT WINAPI _surfaceEnumCallback_GetPrimary( LPDIRECTDRAWSURFACE7 lpDDSurface, LPDDSURFACEDESC2 lpDDSurfaceDesc, LPVOID /*lpContext*/ ) {
    lpDDS[si] = lpDDSurface;
    si++;
    wsprintf(buff2, "surface:%8x, width=%d, height=%d, buffCount:%d\n",
    lpDDSurface, lpDDSurfaceDesc->dwWidth,
    lpDDSurfaceDesc->dwHeight,lpDDSurfaceDesc->dwBackBufferCount);
    mout(buff2);
    if( lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE ) { //Primary
    lpDDSPrimary = lpDDSurface;
    wsprintf(buff2, "primary surface: %8x\n", lpDDSurface);
    mout(buff2);
    // lpDDSurface->GetSurfaceDesc(&ddsd);
    //  return DDENUMRET_CANCEL;

    //lpDDSurface->Release();
    return DDENUMRET_OK;
    }
    //以上是回调函数,下面是枚举
    // Get lpDD
    DWORD addr=0x00385b2c;
    VirtualProtect( ( void * ) addr, 4, PAGE_EXECUTE_READWRITE, &dwOldProtect );
    lpDDAddr=  *((DWORD*)addr);
    lpDD = (struct IDirectDraw7 *)lpDDAddr;// Enum Surface
    mout("now start to enum:\n");
    lpDD->EnumSurfaces( DDENUMSURFACES_DOESEXIST | DDENUMSURFACES_ALL, NULL, NULL, _surfaceEnumCallback_GetPrimary );
    for(int i=0;i<4;i++){
    wsprintf(buff2, "found surface[%d]: %8x\n", i, lpDDS[i]);
    mout(buff2);
    }
      

  6.   

    backBuffer 无法GetDC(),就无法TextOut
      

  7.   

    backBuffer怎么会无法GetDC呢?那那个程序本身是怎么往上绘东西的啊。你看看是不是其它地方错了。
      

  8.   

    不会有错,那个程序是解码MP4视频流数据后,用ddraw加以显示,程序本身用不到GetDC,我用是为了显示文字。
      

  9.   

    那程序要往上面绘东西,Blt总得支持吧?你自己建一个Surface,GetDC后TextOut你的文字,然后Blt到那个BackBuffer上去。