2013-08-03 16 views

risposta

34

La soluzione utilizza la potenza combinata di GetWindowRect() e MapWindowPoints().

GetWindowRect() recupera le coordinate di una finestra relative all'intera area dello schermo visualizzata sul monitor. Abbiamo bisogno di convertire queste coordinate assolute in coordinate relative della nostra finestra principale. Lo MapWindowPoints() trasforma le coordinate date relative ad una finestra in relazione ad un'altra. Quindi abbiamo bisogno di un "handle" dell'area dello schermo e della maniglia della finestra genitore del controllo che stiamo cercando di trovare le coordinate di. Lo schermo è una "finestra" nella terminologia di Windows e si chiama "Desktop". Possiamo accedere all'handle del desktop con la costante HWND_DESKTOP definita in WinUser.h (incluso Windows.h). E possiamo ottenere l'handle della nostra finestra genitore semplicemente chiamando la funzione Win32 GetParent(). Ora abbiamo tutti i parametri necessari per chiamare la funzione MapWindowPoints().

RECT YourClass::GetLocalCoordinates(HWND hWnd) const 
{ 
    RECT Rect; 
    GetWindowRect(hWnd, &Rect); 
    MapWindowPoints(HWND_DESKTOP, GetParent(hWnd), (LPPOINT) &Rect, 2); 
    return Rect; 
} 

MapWindowPoints() è definito come:

int MapWindowPoints(
    _In_  HWND hWndFrom, 
    _In_  HWND hWndTo, 
    _Inout_ LPPOINT lpPoints, 
    _In_  UINT cPoints 
); 

MapWindowPoints() trasformazione delle coordinate relativamente da hWndFrom a hWndTo. Nel nostro caso, eseguiamo la trasformazione da Desktop (HWND_DESKTOP) alla nostra finestra principale (GetParent(hWnd)). Pertanto, la struttura risultante RECT contiene le coordinate relative della finestra figlio (hWnd) relative alla relativa finestra padre.

+1

Oggi ho utilizzato una buona quantità di tempo per trovare una soluzione a questo problema. Ci sono molte informazioni errate e fuorvianti su questo argomento in internet e persino in questo sito. È una grande tragedia che Win32 non fornisce una funzione esplicita per raccogliere queste informazioni, ed è anche terribile che sia molto difficile trovare una buona spiegazione e codice di esempio per la soluzione di questo semplice problema. Sto condividendo la soluzione qui per aiutare altri utenti che la cercheranno in futuro. – hkBattousai

+1

Sei sicuro, questo lavoro su più monitor ??? – Xearinox

+0

@Xearinox Mi rendo conto che sto risuscitando i morti qui, ma ... Sì. Su più monitor, a seconda di quale è il display principale, il metodo restituirà valori altamente negativi o molto positivi per rappresentare le coordinate relative al display principale. Provalo tu stesso usando "SetCursorPos' e vedi dove si posiziona il cursore del mouse. – RectangleEquals

11

che è la soluzione che sto usando sia per Windows o per i controlli (finestre figlio)

RECT rc; 
GetClientRect(hWnd,&rc); 
MapWindowPoints(hWnd,GetParent(hWnd),(LPPOINT)&rc,2); 
+0

Shouldnt si tratti MapWindowPoints (hWnd, GetParent (hWnd), (lpPoint) &rc,1); –

+0

perché sarebbe che, @Erdinc? Ci sono due punti * * a un rettangolo. –

+0

Credo che si ottiene 1 oggetto con 2 punti. –

0

Ecco una funzione che prende gli elementi di entrambe le risposte in qualcosa di usable- in particolare per spostare/ridimensionare coordinate di controllo .
Accetta come parametri un ID di controllo integrale da una risorsa e un handle per il relativo contenitore.
Si dovrebbe anche considerare se il numero ownerHwnd viene ridotto a icona prima di chiamare la funzione ascoltando SIZE_MINIMIZED in WM_SIZE.

BOOL ProcCtrl(int ctrlID, HWND ownerHwnd) 
{ 
    RECT rcClient = {0};   
    HWND hwndCtrl = GetDlgItem(ownerHwnd, ctrlID); 
    if (hwndCtrl) 
    { 
    GetWindowRect(hwndCtrl, &rcClient); //get window rect of control relative to screen 
    MapWindowPoints(NULL, ownerHwnd, (LPPOINT)&rcClient,2); 

    // Set scaling parameters to suit in either of the following functions 
    //if (!MoveWindow(hwndCtrl, rcClient.left, rcClient.top, 
    //rcClient.right-rcClient.left, rcClient.bottom-rcClient.top, TRUE)) 
    { 
     //Error; 
     //return FALSE; 
    } 
    //if (!SetWindowPos(hwndCtrl, NULL, (int)rcClient.left, (int)(rcClient.top), 
    //(int)(rcClient.right - rcClient.left), (int)(rcClient.bottom - rcClient.top), SWP_NOZORDER)) 
    { 
     //Error; 
     //return FALSE; 
    } 
    } 
    else 
    { 
     //hwndCtrl Error; 
     //return FALSE; 
    } 
    return TRUE; 
} 
Problemi correlati