2013-08-03 37 views

Trả lời

34

Giải pháp là sử dụng tổng công suất GetWindowRect()MapWindowPoints().

GetWindowRect() truy lục các tọa độ của cửa sổ có liên quan đến toàn bộ khu vực màn hình bạn thấy trên màn hình của mình. Chúng ta cần phải chuyển đổi các tọa độ tuyệt đối này thành các tọa độ tương đối của khu vực cửa sổ chính của chúng ta. Các MapWindowPoints() biến đổi các tọa độ được đưa ra tương đối so với một cửa sổ tương đối so với một cửa sổ khác. Vì vậy, chúng ta cần một "xử lý" của khu vực màn hình và xử lý của cửa sổ cha mẹ của điều khiển mà chúng tôi đang cố gắng tìm tọa độ. Màn hình là một "cửa sổ" trong thuật ngữ Windows và nó được gọi là "Desktop". Chúng tôi có thể truy cập vào tay cầm của máy tính để bàn theo hằng số HWND_DESKTOP được xác định trong WinUser.h (bao gồm Windows.h là đủ). Và chúng ta có thể nhận được xử lý của cửa sổ cha mẹ của chúng tôi chỉ đơn giản bằng cách gọi hàm Win32 GetParent(). Bây giờ chúng ta có tất cả các tham số cần thiết để gọi hàm MapWindowPoints().

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

MapWindowPoints() được định nghĩa là:

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

MapWindowPoints() chuyển đổi các tọa độ tương đối hWndFrom-hWndTo. Trong trường hợp của chúng tôi, chúng tôi thực hiện chuyển đổi từ Máy tính để bàn (HWND_DESKTOP) sang cửa sổ chính của chúng tôi (GetParent(hWnd)). Do đó, kết cấu RECT giữ tọa độ tương đối của cửa sổ con của chúng ta (hWnd) liên quan đến cửa sổ chính của nó.

+1

Hôm nay tôi đã sử dụng khoảng thời gian hợp lý để tìm giải pháp cho vấn đề này. Có rất nhiều thông tin sai lệch và gây nhầm lẫn về vấn đề này trên internet và ngay cả trong trang web này. Đó là một thảm kịch lớn mà Win32 không đưa ra một chức năng rõ ràng để thu thập thông tin này, và nó cũng kinh khủng đến mức rất khó tìm được lời giải thích và mã ví dụ cho giải pháp của vấn đề đơn giản này. Tôi đang chia sẻ giải pháp ở đây để giúp những người dùng khác tìm kiếm nó trong tương lai. – hkBattousai

+1

Bạn có chắc chắn, công việc này trong nhiều màn hình? – Xearinox

+0

@Xearinox Tôi nhận ra mình đang nuôi những người chết ở đây, nhưng ... Vâng. Trên nhiều màn hình, tùy thuộc vào màn hình chính, phương thức sẽ trả lại giá trị âm hoặc có giá trị dương cao để biểu thị tọa độ tương ứng với màn hình chính. Tự mình thử bằng cách sử dụng 'SetCursorPos' và xem con trỏ chuột nằm ở đâu. – RectangleEquals

11

đó là giải pháp tôi đang sử dụng một trong hai cho các cửa sổ hoặc cho các điều khiển (con cửa sổ)

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

Không phải là MapWindowPoints (hWnd, GetParent (hWnd), (LPPOINT) &rc,1); –

+0

Tại sao nó lại là @Erdinc? Có * hai * điểm trong một trực tiếp –

+0

Tôi nghĩ bạn nhận được 1 đối tượng với 2 điểm –

0

Dưới đây là một chức năng mà sẽ đưa các yếu tố của cả hai câu trả lời vào một cái gì đó usable- đặc biệt đối với di chuyển/thay đổi kích thước kiểm soát tọa độ .
Nó chấp nhận các tham số như một ID điều khiển tích phân từ một tài nguyên và một tay cầm cho vùng chứa của nó.
Bạn cũng nên xem xét liệu ownerHwnd có được giảm thiểu hay không trước khi gọi hàm bằng cách nghe SIZE_MINIMIZED trong 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; 
} 
Các vấn đề liên quan