MapX 在执行 Zoom 时有时会显得非常慢,并且是一层一层绘制出的,有一种想法是如果可以将绘制过程先绘制到内存中然后再一次性拷贝到屏幕上,这不但能节省一些时间,也可以防止闪烁。不知道如何让MapX绘制时直接绘制到内存中?

解决方案 »

  1.   

    仅供参考:
    VOID Paint(HDC hdc) {
    }
    LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
        case WM_PAINT:
            hdc=BeginPaint(hWnd, &ps);
            BitBlt(memDC,0,0,width,height,hdc,0,0,SRCCOPY);
            Paint(memDC);
            BitBlt(hdc,0,0,width,height,memDC,0,0,SRCCOPY);
            EndPaint(hWnd, &ps);
            return 0;
    }
                global_hdc=GetDC(hWnd);
                memDC=CreateCompatibleDC(NULL);
                HBITMAP bmp=CreateCompatibleBitmap(global_hdc,width,height);
                HBITMAP OldBmp=(HBITMAP)SelectObject(memDC,bmp);
                while (GetMessage(&msg, NULL, 0, 0)) {
                    TranslateMessage(&msg);
                    DispatchMessage(&msg);
                }
                SelectObject(global_hdc,OldBmp);
                DeleteObject(bmp);
                DeleteDC(memDC);
                ReleaseDC(hWnd,global_hdc);
      

  2.   

    @赵4老师 问题在于
           1 hdc=BeginPaint(hWnd, &ps);
           2 BitBlt(memDC,0,0,width,height,hdc,0,0,SRCCOPY);
           3  Paint(memDC);
           4  BitBlt(hdc,0,0,width,height,memDC,0,0,SRCCOPY);
           5  EndPaint(hWnd, &ps);
    在第 2步完成后,MapX 控件在执行缩放命令(Zoom)时,会自动往hdc 绘制地图,并同时输出到窗口。而不是在memDC 上绘制,我是希望 memDC 能替换 mapx 的DC
    (既通过 mapxCtr.GetDC()获取的 CDC),当MapX 执行绘制操作时会知道memDC 中,绘制完成后我在根据绘制结束消息拷贝到屏幕上去
      

  3.   

    WinAPIOverride http://jacquelin.potier.free.fr/winapioverride32/
      

  4.   

    @赵4老师 感谢您的热情帮助,WinAPIOverride  看到 在一次缩放过程中MapX 会一直往其DC(简称 DC_Map)中绘制信息,过程包括GetDC—— IsWindow—— ReleaseDC()  但是这些信息对我的目标无有帮助,我是希望在缩放的过程中能用我创建的memDC 来替换DC_Map 这样才能达到不闪烁的目的
      

  5.   

    使用WinAPIOverride,Hook MapX对应进程的GetDC,让其返回你的memDC,……
      

  6.   

    又或者MapX是开源的,直接修改相关源代码使用memDC
      

  7.   

    @赵4老师 使用WinAPIOverride,Hook MapX对应进程的GetDC,让其返回你的memDC,……对于这个我理解了 ,但是执行起来还有很大难度,是否可以直接通过代码方式完成 DC_map 到 memDC 的替换呢。还请赵老师不吝赐教,感恩!
    (另、MapInfo 也可以达到缩放时一次性显示出来的效果,不知MapInfo 是否也采用了 Hook 的方式)
      

  8.   

    注入一例,仅供参考:/*
        Application:    Code Injection in Explorer
        Author:     @_RT
        Compiled on:    Feb 2014
        URL:http://www.codeproject.com/Tips/732044/Code-Injection-2    We will see the different steps involved to perform a code injection into an already running process.    Following are the quick steps through the process of injection.
        1.Get the API addresses that you will be calling from the injected code.
        2.Prepare shell code of your function that you want to get executed from the injected process.
        3.Get the process ID of the running process that you wish to inject into by enumerating through the
          list of processes or by finding the process's window (in case it's a GUI application) by class name or title.
        4.Open the process using its Pid with All Access rights.
        5.Allocate different memory spaces in the process that you are going to inject to with desired access
          rights for holding different segments of your shell code.
            Code part (executable instructions)
            Data part (strings, function parameters, etc.)
        6.Write the allocated memories with the respective values (code and data).
        7.Call CreateRemoteThread API and pass to it the start of allocated memory address where you have
          written your shell code from the process we are injecting.
    */#include <windows.h>
    #pragma comment(lib,"user32.lib")LPVOID addr;
    LPVOID addr2;BOOL InjectExecutable(DWORD dwPid,LPVOID si,LPVOID pi,int sisize,int pisize)
    {
        LPVOID hNewModule;
        HANDLE hProcess;
        CHAR S[]    = { "C:\\Windows\\system32\\notepad.exe" };
        BYTE byt[]  = {0x6A, 0x00, 0x6A, 0x00, 0x6A, 0x00, 0x6A, 0x01, 0x6A, 0x00, 0x6A, 0x00, 0x6A, 0x00, 0x68};
                     //push  0   , push     0, push     0, push     1, push     0, push     0, push     0, push 0xXXXXXXXX
        BYTE byt2[] = {0xE8};//call 0xXXXXXXXX
        BYTE byt3[] = {0x68};//push 0xXXXXXXXX    hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPid);
        if (hProcess == NULL)
        {
            return FALSE;
        }    LPVOID staddr = VirtualAllocEx(hProcess, NULL, sizeof(S), MEM_COMMIT, PAGE_READWRITE);
        WriteProcessMemory(hProcess, staddr, S, sizeof(S), NULL);
        LPVOID fnaddr = VirtualAllocEx(hProcess, NULL, 4, MEM_COMMIT, PAGE_READWRITE);
        WriteProcessMemory(hProcess, fnaddr, pi, sisize, NULL);
        LPVOID fnaddr2 = VirtualAllocEx(hProcess, NULL, 4, MEM_COMMIT, PAGE_READWRITE);
        WriteProcessMemory(hProcess, fnaddr2, si, pisize, NULL);    hNewModule = VirtualAllocEx(hProcess, NULL, 100, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
        if (hNewModule == NULL)
        {
            return FALSE;
        }
        LPTHREAD_START_ROUTINE strtaddr = (LPTHREAD_START_ROUTINE)hNewModule;    WriteProcessMemory(hProcess, hNewModule, byt3, sizeof(byt3), NULL);
        hNewModule = (LPVOID)((int)hNewModule + sizeof(byt3));
        WriteProcessMemory(hProcess, hNewModule, &fnaddr, sizeof(fnaddr), NULL);
        hNewModule = (LPVOID)((int)hNewModule + sizeof(fnaddr));                    // push &pi ;lpProcessInformation
        WriteProcessMemory(hProcess, hNewModule, byt3, sizeof(byt3), NULL);
        hNewModule = (LPVOID)((int)hNewModule + sizeof(byt3));
        WriteProcessMemory(hProcess, hNewModule, &fnaddr2, sizeof(fnaddr2), NULL);
        hNewModule = (LPVOID)((int)hNewModule + sizeof(fnaddr2));                   // push &si ;lpStartupInfo
        WriteProcessMemory(hProcess, hNewModule, byt, sizeof(byt), NULL);           // push 0 , push 0, push 0, push 1, push 0, push 0, push 0, push 0xXXXXXXXX==&S[0];"C:\\Windows\\system32\\notepad.exe"
        hNewModule = (LPVOID)((int)hNewModule + sizeof(byt));                       // lpCurrentDirectory,lpEnvironment,dwCreationFlags,bInheritHandles,lpThreadAttributes,lpProcessAttributes,lpCommandLine,lpApplicationName
        WriteProcessMemory(hProcess, hNewModule, &staddr, sizeof(staddr), NULL);
        hNewModule = (LPVOID)((int)hNewModule + sizeof(staddr));
        WriteProcessMemory(hProcess, hNewModule, byt2, sizeof(byt2), NULL);
        hNewModule = (LPVOID)((int)hNewModule + sizeof(byt2));                      // call CreateProcessA
        addr = (LPVOID)((int)addr - ((int)hNewModule + 4));
        WriteProcessMemory(hProcess, hNewModule, &addr, sizeof(addr), NULL);
        hNewModule = (LPVOID)((int)hNewModule + sizeof(addr));
        WriteProcessMemory(hProcess, hNewModule, byt, 2, NULL);
        hNewModule = (LPVOID)((int)hNewModule + 2);                                 // push 0 ;DWORD dwExitCode   // exit code for this thread
        WriteProcessMemory(hProcess, hNewModule, byt2, sizeof(byt2), NULL);
        hNewModule = (LPVOID)((int)hNewModule + sizeof(byt2));                      // call ExitThread
        addr2 = (LPVOID)((int)addr2 - ((int)hNewModule + 4));
        WriteProcessMemory(hProcess, hNewModule, &addr2, sizeof(addr2), NULL);    CreateRemoteThread(hProcess, 0, 0, strtaddr, NULL, 0, NULL);
        return TRUE;
    }int main()
    {
        _STARTUPINFOA si;
        PROCESS_INFORMATION pi;    ZeroMemory(&si, sizeof(si));
        si.cb = sizeof(si);
        ZeroMemory(&pi, sizeof(pi));    DWORD dwPid;
        HMODULE ldlib = LoadLibraryA("Kernel32.dll");
        addr = GetProcAddress(ldlib, "CreateProcessA");
        addr2 = GetProcAddress(ldlib, "ExitThread");
        HWND hWnd1=FindWindow(NULL, "Program Manager");
        if (NULL==hWnd1) {
            return 1;
        }
        GetWindowThreadProcessId(hWnd1, &dwPid);    InjectExecutable(dwPid,&si,&pi,sizeof(si),sizeof(pi));    return 0;
    }