forum.boolean.name

forum.boolean.name (http://forum.boolean.name/index.php)
-   C++ (http://forum.boolean.name/forumdisplay.php?f=22)
-   -   GetWindowRect (http://forum.boolean.name/showthread.php?t=15110)

impersonalis 12.07.2011 23:30

GetWindowRect
 
Забодал этот косяк: как окна центровать - так пиши костыли.
Вот что написано во всех мануалах:
Цитата:

Функция GetWindowRect отыскивает размеры рамки ограничивающей прямоугольник определяемого окна. Размеры даны в экранных координатах, которые расположены относительно левого верхнего угла экрана.
Безусловно - поля bottom и right содержат в себе координаты y и x правой нижней точки окна. Проблема в том, что left и top содержат нули.
Ну т.е. для окна с левым верхним углом в 100;50 и размерами 100;100,
результат будет
left=0
top=0
bottom=150
right=200
Ну блин!
Т.е. функция ведёт себя аналогично GetClientRect (которая возвращает координаты в системе отсчёта рабочей области).
Оценить левый угол, исходя из разности GetClientRect и GetWindowRect нельзя, т.к. в уравнении участвуют ещё неизвестные параметры, характеризующие толщину границы окна, шапку (её может и не быть), системное меню, статус бар и прочее.
При этом в кодах разных прогеров часто встречается код, подразумевающий именно такой результат работы, как описан в учебнике.
Запускаю отладку - нули.
ЧЯДНТ?

mfc: http://www.firststeps.ru/mfc/winapi/r.php?72
!mfc: http://vsokovikov.narod.ru/New_MSDN_...windowrect.htm

.Squid 13.07.2011 02:52

Ответ: GetWindowRect
 
Если нужно отцентрировать окно, то сначала получаешь его размеры (у тебя уже есть).
Затем получаешь размер декстопа:
Код:

int dx = GetSystemMetrics(SM_CXSCREEN);
int dy = GetSystemMetrics(SM_CYSCREEN);

Центрируешь:
Код:

int x = (dx - width) >> 1;
int y = (dy - height) >> 1;
SetWindowPos(rWnd, HWND_TOP, x, y, width, height, SWP_SHOWWINDOW);


Randomize 13.07.2011 04:25

Ответ: GetWindowRect
 
Цитата:

Сообщение от .Squid (Сообщение 195290)
Код:

int x = (dx - width) >> 1;
int y = (dy - height) >> 1;


Что означает конструкция ">> 1"?

.Squid 13.07.2011 05:55

Ответ: GetWindowRect
 
Бинарный сдвиг вправо на указанное число битов.

impersonalis 13.07.2011 10:33

Ответ: GetWindowRect
 
Цитата:

Сообщение от .Squid (Сообщение 195290)
Если нужно отцентрировать окно, то сначала получаешь его размеры (у тебя уже есть).
Затем получаешь размер декстопа:
Код:

int dx = GetSystemMetrics(SM_CXSCREEN);
int dy = GetSystemMetrics(SM_CYSCREEN);

Центрируешь:
Код:

int x = (dx - width) >> 1;
int y = (dy - height) >> 1;
SetWindowPos(rWnd, HWND_TOP, x, y, width, height, SWP_SHOWWINDOW);


НУ, собственно - так и собирался (только размеры декстопа через его дескриптор хотел GetDesktopWindow). Но всё равно костыли - размеры окна своего придётся либио фиксировать либо кажный раз править исходник (т.к. GetWindowRect примешивает к размерам ещё и смещение левого края, а GetClientRect не учитывает ряд отсупов).

SBJoker 13.07.2011 10:33

Ответ: GetWindowRect
 
Деление на два нацело.

impersonalis 13.07.2011 11:23

Ответ: GetWindowRect
 
Стал искать альтернативные пути.
Сперва хотел через
GetWindowInfo получить структуру WINDOWINFO, но оно чего-то заломалось, да и чрезмерно монструозно.
Поэтом применил другой костыль.
GetWindowPlacement и анализ поля rcNormalPosition структуры WINDOWPLACEMENT
Код:

int tx,ty;
        HDWP windefer;
        WINDOWPLACEMENT GCodeInfo;

        int DeskTopXSize=GetSystemMetrics(SM_CXSCREEN);
        int DeskTopYSize=GetSystemMetrics(SM_CYSCREEN);

        GCodeInfo.length=sizeof(WINDOWPLACEMENT);
        GetWindowPlacement(hSplashWnd, &GCodeInfo);

        int width=GCodeInfo.rcNormalPosition.right-GCodeInfo.rcNormalPosition.left;
        int height=GCodeInfo.rcNormalPosition.bottom-GCodeInfo.rcNormalPosition.top;

        tx=(DeskTopXSize - width) >> 1;
        ty=(DeskTopYSize - height) >> 1;

Можно аналогично запилить и центровку относительно родительского окна. В моём случае, достаточно по декстопу.

wolfhound512 13.07.2011 11:49

Ответ: GetWindowRect
 
Цитата:

Сообщение от .Squid (Сообщение 195290)
Если нужно отцентрировать окно, то сначала получаешь его размеры (у тебя уже есть).
Затем получаешь размер декстопа:
Код:

int dx = GetSystemMetrics(SM_CXSCREEN);
int dy = GetSystemMetrics(SM_CYSCREEN);

Центрируешь:
Код:

int x = (dx - width) >> 1;
int y = (dy - height) >> 1;
SetWindowPos(rWnd, HWND_TOP, x, y, width, height, SWP_SHOWWINDOW);


Окно получается не совсем по центру, т.к. не учитывается размер рамки.
Я центрирую так:
Код:

        /* (width, height - размеры окна) */

        /* Get Desktop size */
        tagRECT rect;
        GetClientRect( GetDesktopWindow(), &rect );

        /* Calc position and size of the new window */
        rect.left = (rect.right - width) >> 1;
        rect.right = rect.left + width;
        rect.top = (rect.bottom - height) >> 1;
        rect.bottom = rect.top + height;

        /* Adjust window size */
        AdjustWindowRect(&rect, GetWindowLong(_vpWindow, GWL_STYLE), false);
        SetWindowPos(_vpWindow, 0, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, 0);

Клиентская область получается ровно по центру.

impersonalis 13.07.2011 11:53

Ответ: GetWindowRect
 
2wolfhound512
Да, читал про эту функцию, но мне показалось* это ещё большим костылём (могу ошибаться).
http://www.firststeps.ru/mfc/winapi/r.php?73 :
Цитата:

Правда эта функция не учитывает, что меню может быть в два ряда, если окно маленькое. Так же она не учитывает стили WS_VSCROLL или WS_HSCROLL. Для этого нужно вызывать GetSystemMetrics().
Хотя вышеперечисленных свистелок моё окно не имеет (сплеш-скрин)

RegIon 13.07.2011 13:25

Ответ: GetWindowRect
 
Цитата:

Сообщение от Randomize (Сообщение 195295)
Что означает конструкция ">> 1"?

рандом,ты это не знал???смешение наверно каждый знает что такое,но не знает как пользоватся

научити меня нормально этим пользоваться,а то мне проще поделить на 10,чем смешение использовать

den 13.07.2011 13:38

Ответ: GetWindowRect
 
смешение != смещение

HolyDel 13.07.2011 13:44

Ответ: GetWindowRect
 
на 10 нельзя
можно только на 8 или на 16

RegIon 13.07.2011 14:07

Ответ: GetWindowRect
 
Цитата:

на 10 нельзя
можно только на 8 или на 16
а...точняк,поБайтно же

impersonalis 13.07.2011 14:34

Ответ: GetWindowRect
 
ПОБИТОВО!!

RegIon 13.07.2011 14:41

Ответ: GetWindowRect
 
Цитата:

Сообщение от impersonalis (Сообщение 195329)
ПОБИТОВО!!

зы,один байт=8 бит...невкурсе??


Часовой пояс GMT +4, время: 16:59.

vBulletin® Version 3.6.5.
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Перевод: zCarot