2015-12-07 54 views
12

Pracuję nad aplikacją, która ustawia okna na ekranie w stylu siatki. Podczas uruchamiania tego w systemie Windows 10 istnieje ogromna luka między oknami. Dalsze dochodzenie pokazuje, że GetWindowRect zwraca nieoczekiwane wartości, w tym niewidoczną granicę, ale nie mogę go uzyskać, aby zwrócić rzeczywiste wartości z widoczną ramką.GetWindowRect zwraca rozmiar z "niewidzialnymi" granicami

1) This thread sugeruje, że jest to zgodne z projektem i można go "naprawić", łącząc się z winver = 6. Moje środowisko to nie pozwala, ale próbowałem zmieniając PE MajorOperatingSystemVersion i MajorSubsystemVersion do 6 nie wpływa

2) Ten sam wątek sugeruje również za pomocą DwmGetWindowAttribute z DWMWA_EXTENDED_FRAME_BOUNDS uzyskać rzeczywiste współrzędne z DWM, który działa, ale środkiem zmieniając się wszędzie, gdzie dostaje się współrzędne okna. Nie pozwala również na ustawienie wartości, co pozwala nam odwrócić proces, aby móc ustawić rozmiar okna.

3) This question sugeruje, że w tym procesie brakuje świadomości DPI. Ani ustawienie flagi świadomości DPI w manifeście, ani wywołanie SetProcessDpiAwareness nie przyniosło żadnych rezultatów.

4) Z kaprysu próbowałem także dodać flagi zgodności Windows Vista, 7, 8, 8.1 i 10, a motywy systemu Windows są widoczne bez zmian.

Screenshot of a "fullscreen" window with gaps all round To okno zostanie przeniesiona do 0x0, 1280x1024, rzekomo, aby wypełnić cały ekran, a kiedy zapytań współrzędnych z powrotem, mamy te same wartości. Okno jest jednak w rzeczywistości o 14 pikseli węższe, aby uwzględnić ramkę na starszych wersjach systemu Windows.

Jak przekonać system Windows do pracy z rzeczywistymi współrzędnymi okna?

+0

na pełne okno lub małym oknie, jakie są współrzędne spodziewasz i współrzędne otrzymujesz? –

+0

@barmak Chciałbym, aby po ustawieniu wartości 0x0 okno znajdowało się w lewym górnym rogu, a nie 7x0, w rzeczywistości jest wyświetlane jako. Zobacz zrzut ekranu. – Deanna

+0

Czy to jest VB6 lub VB.NET? – IInspectable

Odpowiedz

11

System Windows 10 ma cienkie niewidoczne obramowania po lewej, prawej i na dole, służy do uchwycenia myszy w celu zmiany rozmiaru. Granice może wyglądać następująco: 7,0,7,7 (lewy, górny, prawy, dolny)

Po wywołaniu SetWindowPos umieścić okno na to współrzędne:
0, 0, 1280, 1024

Okno odbierze te dokładne współrzędne, i GetWindowRect zwróci te same współrzędne. Ale wizualnie, okno pojawia się tutaj:
7, 0, 1273, 1017

Można oszukać okno i powiedzieć jej, aby przejść tutaj zamiast:
-7, 0, 1287, 1031

Aby to zrobić, mamy system Windows grubości 10 granicznej:

RECT rect, frame; 
GetWindowRect(hwnd, &rect); 
DwmGetWindowAttribute(hwnd, DWMWA_EXTENDED_FRAME_BOUNDS, &frame, sizeof(RECT)); 

//rect should be `0, 0, 1280, 1024` 
//frame should be `7, 0, 1273, 1017` 

RECT border; 
border.left = frame.left - rect.left; 
border.top = frame.top - rect.top; 
border.right = rect.right - frame.right; 
border.bottom = rect.bottom - frame.bottom; 

//border should be `7, 0, 7, 7` 

Następnie przesunięcie prostokąt tak:

rect.left -= border.left; 
rect.top -= border.top; 
rect.right += border.left + border.right; 
rect.bottom += border.top + border.bottom; 

//new rect should be `-7, 0, 1287, 1031` 

O ile nie ma prostszego rozwiązania!

+0

I właśnie to nie chciałem zrobić, hack, aby dowiedzieć się, co to jest offset i dostosować rzeczywiste wartości, które stosujemy. Dziękuję i mogę nadal używać tego, jeśli nie ma innej alternatywy. – Deanna

+1

To się po prostu polepsza ... Ta metoda działa tylko PO pokazanym oknie :(Do tego czasu funkcja DWM po prostu zwraca to samo, co 'GetWindowRect'. – Deanna

+0

Och, nie myślałem o tym. Aby usunąć tę odpowiedź, zauważyłem inne problemy z nim.Pamiętaj, że 'SetWindowPos' i' GetWindowRect' działają poprawnie.Zapytałeś o granice i system podaje swoje granice.Jednym problemem jest to, że granice są niewidoczne w systemie Windows 10, więc wygląda na to, że okno jest w niewłaściwym miejscu Visual Studio IDE ma swoje własne okna narzędziowe, gdy okno narzędzi jest zadokowane, nie używa granic ani niestandardowego 'NC_PAINT', a gdy jego okno narzędziowe jest pływające, to używa domyślne granice. Myślę, że chcesz coś podobnego? –

0

Jak przekonać system Windows do pracy z rzeczywistymi współrzędnymi okna?

Już pracujesz z prawdziwymi współrzędnymi. Windows10 po prostu zdecydował się ukryć granice przed oczami. Ale mimo to wciąż tam są. Po przejściu przez krawędzie okna kursor zmieni się w kursor zmiany rozmiaru, co oznacza, że ​​nadal znajduje się nad oknem.

Jeśli chcesz, aby Twoje oczy, aby dopasować to, co Windows jest informacją, można spróbować odsłaniając te granice, tak aby były widoczne ponownie, korzystając z motywu Aero Lite:

http://winaero.com/blog/enable-the-hidden-aero-lite-theme-in-windows-10/

+1

Taki wniosek doszedłem. Zmiana motywu nie jest jednak możliwa, ponieważ jest to dostępna na rynku aplikacja. Zmuszanie tematu do użytkowników końcowych jest ogólnie uważane za złą praktykę :-) – Deanna

+1

Zgadzam się, zmiana tematu jest złym pomysłem i czymś, czego nie wymagam od moich użytkowników. Ale wciąż narzekają na luki :( – mikew

-1

można zareagować na WM_NCCALCSIZE wiadomość, zmodyfikuj domyślne zachowanie WndProc, aby usunąć niewidoczne obramowanie.

Jak this document i this document wyjaśnić, kiedy wParam> 0, na żądanie wParam.Rgrc[0] zawiera nowe współrzędne okna, a kiedy powraca procedurze Response wParam.Rgrc[0] zawiera współrzędne nowego prostokąta klienta.

Przykładowy kod golang:

case win.WM_NCCALCSIZE: 
    log.Println("----------------- WM_NCCALCSIZE:", wParam, lParam) 

    if wParam > 0 { 
     params := (*win.NCCALCSIZE_PARAMS)(unsafe.Pointer(lParam)) 
     params.Rgrc[0].Top = params.Rgrc[2].Top 
     params.Rgrc[0].Left = params.Rgrc[0].Left + 1 
     params.Rgrc[0].Bottom = params.Rgrc[0].Bottom - 1 
     params.Rgrc[0].Right = params.Rgrc[0].Right - 1 
     return 0x0300 
    }