Je tente de définir mes propriétés de contexte de périphérique préférées dans le message WM_CREATE
, puis de l'utiliser dans le message WM_PAINT
. Ma méthode consiste à utiliser les fonctions SaveDC
et RestoreDC
respectivement dans les messages WM_CREATE
et WM_PAINT
. Mais le résultat ne répond pas à mes besoins. Ce dont j'ai vraiment besoin, c'est de montrer un cercle au centre de la zone client.La fonction "SaveDC" et "RestoreDC" ne peut-elle pas être utilisée dans un code de traitement de message différent?
#include <windows.h>
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
static TCHAR szAppName[] = TEXT ("HelloWin") ;
HWND hwnd ;
MSG msg ;
WNDCLASS wndclass ;
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
wndclass.lpszMenuName = NULL ;
wndclass.lpszClassName = szAppName ;
if (!RegisterClass (&wndclass))
{
MessageBox (NULL, TEXT ("This program requires Windows NT!"),
szAppName, MB_ICONERROR) ;
return 0 ;
}
hwnd = CreateWindow (szAppName, // window class name
TEXT ("The Hello Program"), // window caption
WS_OVERLAPPEDWINDOW, // window style
CW_USEDEFAULT, // initial x position
CW_USEDEFAULT, // initial y position
CW_USEDEFAULT, // initial x size
CW_USEDEFAULT, // initial y size
NULL, // parent window handle
NULL, // window menu handle
hInstance, // program instance handle
NULL) ; // creation parameters
ShowWindow (hwnd, iCmdShow) ;
UpdateWindow (hwnd) ;
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
return msg.wParam ;
}
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HDC hdc ;
PAINTSTRUCT ps ;
RECT rect;
static int nSavedDC;
switch (message)
{
case WM_CREATE:
hdc = GetDC(hwnd);
SetMapMode(hdc, MM_LOMETRIC);
GetClientRect(hwnd, &rect);
SetViewportOrgEx(hdc, rect.right/2, rect.bottom/2, NULL);
nSavedDC = SaveDC(hdc); //I want to save the current state of device context to be used in WM_PAINT message.
ReleaseDC(hwnd, hdc);
return 0;
case WM_PAINT:
hdc = BeginPaint (hwnd, &ps) ;
RestoreDC(hdc, nSavedDC); //Restore the the state of device context which is saved in WM_CREATE message.
Ellipse(hdc, -100, 100, 100, -100);
EndPaint (hwnd, &ps) ;
return 0 ;
case WM_DESTROY:
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
Ce code ne fonctionnera jamais. Vous ne pouvez pas appeler 'ReleaseDC (hwnd, hdc);'; l'appel approprié serait 'ReleaseDC (hwnd, nSavedDc);', ce qui, bien entendu, n'aurait aucun sens. Pourquoi pensez-vous que vous devez sauvegarder '' SaveDC' dans 'WM_CREATE' en premier lieu? Il n'y a aucune utilisation dans le code que vous avez écrit pour n'importe quel but raisonnable, alors que pensez-vous exactement que vous accomplissez ici? Qu'essayez-vous de faire? –
Ce n'est pas comme ça que fonctionnent les DC. Techniquement, vous êtes supposé charger manuellement le DC avec son état à chaque fois, parce que vous n'êtes pas sûr d'avoir le même DC à chaque fois - ils sont dans une piscine, ou quelque chose comme ça. (Il y a des façons d'exiger un DC spécifique pour chaque fenêtre, mais ce sont des retards de Windows 16 bits qui ont beaucoup d'embûches de nos jours qui peuvent produire des résultats spectaculaires dans des programmes suffisamment compliqués.) Raymond Chen a beaucoup sur le sujet. Chargez simplement votre état chaque fois que vous appelez 'BeginPaint()' ou 'GetDC()' et réinitialisez-le avant de l'annuler. – andlabs
@KenWhite 'ReleaseDC (hwnd, nSavedDc);' est complètement faux car 'nSavedDc' est un entier. Le code 'ReleaseDC (hwnd, hdc);' d'origine est correct. – VTT