Электронная библиотека книг Александра Фролова и Григория Фролова.
 
Библиотека
Братьев
Фроловых
Электронная библиотека книг Александра Фролова и Григория Фролова.
Библиотека системного программиста
Программирование на JAVA
ПК. Шаг за шагом
Другие книги
Восстановление данных
Антивирусная защита
Статьи для
программистов
Пользователю компьютера

Операционная система Microsoft Windows 3.1 для программиста

© Александр Фролов, Григорий Фролов
Том 11, М.: Диалог-МИФИ, 1993, 269 стр.

[Назад] [Содеожание] [Дальше]

4.6. Определение расположения окна

В предыдущем разделе мы научили вас определять размеры окна. Другая важная задача - определение расположения окна на экране видеомонитора.

Когда вы перемещаете окно (например, при помощи мыши), функция окна получает сообщение WM_MOVE. Вместе с этим сообщением функция окна получает новые координаты внутренней области окна:

Параметр Описание
wParam Не используется
LOWORD(lParam) Новая X-координата верхнего левого угла внутренней области окна
HIWORD(lParam) Новая Y-координата верхнего левого угла внутренней области окна

Для перекрывающихся (overlapped) и временных (pop-up) окон координаты отсчитываются от верхнего левого угла экрана. Для дочерних (child) окон эти координаты отсчитываются от верхнего левого угла внутренней области родительского окна.

В любой момент времени приложение может определить расположение и размеры окна, вызвав функцию GetWindowRect. Эта функция имеет следующий прототип:

void WINAPI GetWindowRect(HWND, RECT FAR*);

Первый параметр задает идентификатор окна, для которого необходимо определить расположение и размер.

Второй параметр является дальним указателем на структуру типа RECT. В эту структуру будет записана информация о расположении и размере прямоугольной области, ограничивающей окно, с учетом заголовка, рамки и полос просмотра (если они заданы). Все координаты отсчитываются от левого верхнего угла экрана.

Для демонстрации использования сообщения WM_MOVE и функции GetWindowRect мы подготовили приложение WPOS. Это приложение по своей структуре аналогично приложению WSIZE, которое было рассмотрено в предыдущем разделе.

В файле wpos.cpp (листинг 4.12) расположена функция WinMain, создающая главное окно приложения и цикл обработки сообщений.


Листинг 4.12. Файл wpos\wpos.cpp


// ----------------------------------------
// Определение расположения окна
// ----------------------------------------

#define STRICT
#include <windows.h>
#include <mem.h>

BOOL InitApp(HINSTANCE);
LRESULT CALLBACK _export WndProc(HWND, UINT, WPARAM, LPARAM);

char const szClassName[]   = "WPOSAppClass";
char const szWindowTitle[] = "WPOSApplication";

// =====================================
// Функция WinMain
// =====================================
#pragma argsused

int PASCAL
WinMain(HINSTANCE hInstance,
        HINSTANCE hPrevInstance,
        LPSTR     lpszCmdLine,
        int       nCmdShow)
{
  MSG  msg;   // структура для работы с сообщениями
  HWND hwnd;  // идентификатор главного окна приложения

  if(!InitApp(hInstance))
      return FALSE;

  hwnd = CreateWindow(
    szClassName,         // имя класса окна
    szWindowTitle,       // заголовок окна
    WS_OVERLAPPEDWINDOW, // стиль окна
    CW_USEDEFAULT,       // задаем размеры и расположение
    CW_USEDEFAULT,       // окна, принятые по умолчанию 
    CW_USEDEFAULT,
    CW_USEDEFAULT,
    0,                   // идентификатор родительского окна
    0,                   // идентификатор меню
    hInstance,           // идентификатор приложения
    NULL);               // указатель на дополнительные
                         // параметры
  if(!hwnd)
    return FALSE;

  ShowWindow(hwnd, nCmdShow);
  UpdateWindow(hwnd);

  while(GetMessage(&msg, 0, 0, 0))
  {
    DispatchMessage(&msg);
  }
  return msg.wParam;
}

// =====================================
// Функция InitApp
// =====================================

BOOL
InitApp(HINSTANCE hInstance)
{
  ATOM aWndClass; // атом для кода возврата
  WNDCLASS wc;    // структура для регистрации
                  // класса окна

  memset(&wc, 0, sizeof(wc));
  wc.style = 0;
  wc.lpfnWndProc = (WNDPROC) WndProc;
  wc.cbClsExtra = 0;
  wc.cbWndExtra = 0;
  wc.hInstance = hInstance;
  wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
  wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
  wc.lpszMenuName = (LPSTR)NULL;
  wc.lpszClassName = (LPSTR)szClassName;

  aWndClass = RegisterClass(&wc);
  return (aWndClass != 0);
}

Функция окна (листинг 4.13) обрабатывает сообщения WM_PAINT, WM_MOVE, WM_SIZE, WM_LBUTTONDOWN и, конечно, WM_DESTROY.


Листинг 4.13. Файл wpos\wndproc.cpp


// =====================================
// Функция WndProc
// =====================================

#define STRICT
#include <windows.h>
#include <stdio.h>

LRESULT CALLBACK _export
WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
  HDC hdc;             // индекс контекста устройства
  PAINTSTRUCT ps;      // структура для рисования

  // Координаты окна
  static WORD   xPos;
  static WORD   yPos;

  switch (msg)
  {
    case WM_PAINT:
    {
      char buf[80]; 

      hdc = BeginPaint(hwnd, &ps);

      sprintf(buf, "%4.4dx%4.4d   ", xPos, yPos);

      // Выводим координаты окна
      TextOut(hdc, 0, 0, buf, 12);

      EndPaint(hwnd, &ps);
      return 0;
    }

    case WM_MOVE:
    {
      // X-координата левого верхнего угла
      // внутренней области окна
      xPos = LOWORD(lParam);

      // Y-координата левого верхнего угла
      // внутренней области окна
      yPos = HIWORD(lParam);

      // Отмечаем все окно как требующее
      // обновления
      InvalidateRect(hwnd, NULL, TRUE);

      // Посылаем себе сообщение WM_PAINT
      UpdateWindow(hwnd);
      return 0;
    }

    case WM_SIZE:
    case WM_LBUTTONDOWN:
    {
      RECT rc;
      char buf[80];

      hdc = GetDC(hwnd);

      // Определяем размеры прямоугольника,
      // ограничивающего окно
      GetWindowRect(hwnd, &rc);

      sprintf(buf, "%4.4dx%4.4d %4.4dx%4.4d      ",
        rc.top,
        rc.left,
        rc.right,
        rc.bottom);

      // Выводим размеры внутренней области окна
      TextOut(hdc, 0, 20, buf, 25);

      ReleaseDC(hwnd, hdc);
      return 0;
    }

    case WM_DESTROY:
    {
      PostQuitMessage(0);
      return 0;
    }
  }
  return DefWindowProc(hwnd, msg, wParam, lParam);
}

Сообщение WM_MOVE передается окну, когда оно отображается функцией ShowWindow, или при изменении размера окна. Наш обработчик сообщения WM_MOVE сохраняет экранные координаты внутренней области окна в переменных с именами xPos и yPos. После сохранения координат функция окна объявляет все окно как требующее обновления и посылает само себе сообщение WM_PAINT, для чего вызывает функцию UpdateWindow:

case WM_MOVE:
{
  xPos = LOWORD(lParam);
  yPos = HIWORD(lParam);
  InvalidateRect(hwnd, NULL, TRUE);
  UpdateWindow(hwnd);
  return 0;
}

Обработчик сообщения WM_PAINT выводит координаты в левом верхнем углу внутренней области окна. Перемещая окно при помощи мыши, вы можете проследить за изменением текущих координат внутренней области окна.

Для сообщений WM_SIZE и WM_LBUTTONDOWN используется общий обработчик. Он вызывает функцию GetWindowRect, с помощью которой определяет координаты и размер прямоугольной области, ограничивающей окно. Координаты левого верхнего угла и правого нижнего угла этой области выводятся во второй строке внутренней области окна (рис. 4.2).

Рис. 4.2. Главное окно приложения WPOS

При перемещении главного окна приложения WPOS первая строка обновляется автоматически, при этом вторая строка стирается. Если после перемещения сделать щелчок мышью внутри окна или изменить его размер, появится вторая строка. В ней будут отображены координаты прямоугольной области, ограничивающей окно.

Для создания приложения был использован файл определения модуля, приведенный в листинге 4.14.


Листинг 4.14. Файл wpos\wpos.def


; =============================
; Файл определения модуля
; =============================
NAME        WPOS
DESCRIPTION 'Приложение WPOS, (C) 1994, Frolov A.V.'
EXETYPE     windows
STUB        'winstub.exe'
STACKSIZE   5120
HEAPSIZE    1024
CODE        preload moveable discardable
DATA        preload moveable multiple

Программный интерфейс операционной системы Windows версии 3.1 содержит еще одну функцию, полезную при определении расположения на экране и размеров окна. Эта функция имеет имя GetWindowPlacement и следующий прототип:

BOOL WINAPI GetWindowPlacement (HWND hwnd,
     WINDOWPLACEMENT FAR* lpwndpl);

Первый параметр функции (hwnd) задает идентификатор окна, для которого нужно определить расположение и размеры.

Второй параметр (lpwndpl) является дальним указателем на структуру типа WINDOWPLACEMENT, определенную в файле windows.h:

typedef struct tagWINDOWPLACEMENT
{
    UINT  length;
    UINT  flags;
    UINT  showCmd;
    POINT ptMinPosition;
    POINT ptMaxPosition;
    RECT  rcNormalPosition;
} WINDOWPLACEMENT;

Поле length определяет размер структуры WINDOWPLACEMENT в байтах.

Поле flags после вызова функции GetWindowPlacement всегда равно нулю. Это поле содержит флаги, определяющие положение минимизированного окна и способ, которым окно будет восстановлено.

Поле showCmd после вызова функции GetWindowPlacement имеет значение SW_SHOWMAXIMIZED для максимизированного окна, SW_SHOWMINIMIZED для минимизированного окна и SW_SHOWNORMAL в остальных случаях.

Поле ptMinPosition определяет положение верхнего левого угла окна, когда оно минимизировано.

Поле ptMaxPosition определяет положение верхнего левого угла окна, когда оно максимизировано.

Поле rcNormalPosition определяет положение верхнего левого угла окна, размеры которого восстановлены до нормальных.

Для указания положения верхнего левого угла максимизированного и минимизированного окна используется структура POINT, определенная в файле windows.h:

typedef struct tagPOINT
{
  int x;
  int y;
} POINT;
[Назад] [Содеожание] [Дальше]


Создание интернет-магазинов: http://www.shop2you.ru/ © Александр Фролов, Григорий Фролов, 1991-2016