Tak jak w temacie, czyli jest HWND (nie moje, bo np. systemowe kontrolki) i muszę na nim coś narysować.

Ktoś powie: subclassuj i rysuj - i owszem na początku też tak pomyślałem i zrobiłem, ale to nie działa na, np. systemowym przycisku, kiedy zostanie naciśnięty i puszczony WM_PAINT nie jest wykonywany.

Pomyślałem sobie... cóż... w BN_CLICKED button musi być ręcznie rysowany przez GetDC/ReleaseDC.
No więc postanowiłem podmienić ReleaseDC na moją funkcję, gdzie bym dorysował to co mi potrzeba, przed zakończeniem rysowania, w tym celu na podstawie kodu: http://vexillium.org/?sec-dllsp autorstwa gynvael'a. Podmieniam ReleaseDC w importach wszystkich modułów:

int (__stdcall *orginalReleaseDC)(HWND, HDC);
int __stdcall myReleaseDC(HWND hwnd, HDC hdc)
{
  //own draw
  Rectangle(hdc, 0, 0, 10, 10);
  
  return orginalReleaseDC(hwnd, hdc);
}

//[.........]

        const char* const DLLName = "user32.dll";
        char FuncName[256] = "ReleaseDC";
        orginalReleaseDC = (int(__stdcall*)(HWND,HDC))GetProcAddress(GetModuleHandle(DLLName), FuncName);
        
        HANDLE hProc = GetCurrentProcess();
        HMODULE modules[2048];
        DWORD m = 0;
        BOOL ret = EnumProcessModules(hProc, modules, sizeof(modules), &m);
        m /= sizeof(HMODULE);
        for(int i = 0; i < m; ++i)
        {
        char buffer[245];
        GetModuleFileName(modules[i], buffer, sizeof(buffer));
          
          unsigned long MainVA = (unsigned long)modules[i];//GetModuleHandle(0);
        if(*(unsigned short*)MainVA != *(unsigned short*)"MZ") return NULL;
        IMAGE_DOS_HEADER *DosHeader = (IMAGE_DOS_HEADER*)MainVA;
        IMAGE_NT_HEADERS *NtHeaders = (IMAGE_NT_HEADERS*)(MainVA + DosHeader->e_lfanew);
        if(NtHeaders->Signature != IMAGE_NT_SIGNATURE) continue;

        IMAGE_DATA_DIRECTORY *ImportDirectory = &NtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
        if(!ImportDirectory->VirtualAddress) continue; //ntdll.dll nie ma tu importów
        IMAGE_IMPORT_DESCRIPTOR *ImportDescriptor = (IMAGE_IMPORT_DESCRIPTOR*)(MainVA + ImportDirectory->VirtualAddress);
        
        for(; ImportDescriptor->Name; ImportDescriptor++)
        {
          const char* str = (const char*)(MainVA + ImportDescriptor->Name);
          if(stricmp((const char*)(MainVA + ImportDescriptor->Name), DLLName) == 0) break;
        }

          const char* DN = (const char*)ImportDescriptor->Name;
          if(ImportDescriptor->Name == 0) continue;

        IMAGE_THUNK_DATA32 *FThunk, *OThunk;
        FThunk = (IMAGE_THUNK_DATA32*)(MainVA + ImportDescriptor->FirstThunk);
        OThunk = (IMAGE_THUNK_DATA32*)(MainVA + ImportDescriptor->OriginalFirstThunk);
        for(; OThunk->u1.AddressOfData; OThunk++, FThunk++)
        {
          if(OThunk->u1.Ordinal & IMAGE_ORDINAL_FLAG32) continue;
          IMAGE_IMPORT_BY_NAME *ImportFuncName = (IMAGE_IMPORT_BY_NAME*)(MainVA + OThunk->u1.AddressOfData);
          const char* FN = (const char*)ImportFuncName->Name;
          if(strcmp((const char*)ImportFuncName->Name, FuncName) != 0) continue;
          //orginalReleaseDC = (int (_stdcall*)(HWND, HDC))FThunk->u1.Function; //save old function

          DWORD OldRight, Temp;
          VirtualProtect(&FThunk->u1.Function, 4, PAGE_EXECUTE_READWRITE, &OldRight);
          FThunk->u1.Function = (DWORD)myReleaseDC;
          VirtualProtect(&FThunk->u1.Function, 4, OldRight, &Temp);
        
        }
      }

Efekt jest taki:
http://img543.imageshack.us/img543/2974/omgy.png
Jak widać niektóre okna mają szare kwadraciki, szare to wywołanie EndPaint (też podmieniłem). No i jak zwykle, podstawowe kontrolki (Button, Edit i ComboBox) nie wołają mojego ReleaseDC ani EndPaint.
Wyjaśnieniem tego byłoby CS_OWNDC, bo wtedy nie trzeba by wołać Get/ReleaseDC, bo może taka kontrolka zachować sobie HDC i rysować bez ich wołania, ale testowałem i Button tego stylu nie ma, więc jedynym wyjaśnieniem jest to, że jednak po prostu kontrolka woła te funDC, ale z jakiegoś powodu nie są one podmienione na moje, a osobiście sprawdzałem i ReleaseDC w importach "comctl32.dll" także jest podmieniane.

Może ktoś będzie wiedział jak dobrać się do rysowania kontrolki, bo ja już od kilku dni nie mogę.

Całkiem innym pomysłem jest oczywiście stworzenie okienka na którym bym rysował to co trzeba i sterowanie nim tak, aby zawsze było nad tą kontrolką na której chcę coś rysować i nie rysować fizycznie na kontrolce, ale na tym okienku, ale wtedy na daną kontrolkę nie będzie dało się kliknąć, a trzeba mieć tę interakcyjność. Próbowałem przekazywać komunikaty WM_KEY* i WM_BUTTON do okienka poniżej, ale bez skutku.