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 бит...невкурсе??

impersonalis 13.07.2011 15:11

Ответ: GetWindowRect
 
смещение на один бит.
деление (умножение) на 2,4,8..
не толсти

SBJoker 13.07.2011 15:17

Ответ: GetWindowRect
 
Костян, не хами, если сам тупой, нефиг это отрицать. Именно побитово, т.к. это сдвиг бит!

Randomize 13.07.2011 15:48

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

Сообщение от Костян (Сообщение 195310)
рандом,ты это не знал???смешение наверно каждый знает что такое,но не знает как пользоватся

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

Я в уме предположил, что это оно. Но в плюсах я никогда битовыми операциями ещё не занимался и решил уточнить.
Здоровая любознательность и только.
Я более привык к Shl и Shr

.Squid 13.07.2011 15:55

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

Сообщение от wolfhound512 (Сообщение 195306)
Окно получается не совсем по центру, т.к. не учитывается размер рамки.
...
Клиентская область получается ровно по центру.

Ну говорилось о центрировании окна, а не клиентской области. Что спросили, то и ответил.


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

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