На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
В этом разделе можно создавать темы, которые относятся к поколению 32-битных компиляторов.
Здесь решаются вопросы портирования кода из старого доброго Турбо Паскаля в FPC, TMT, VP, GPC компиляторы, а также особенностей программирования на них для Windows/Linux и других ОС.
Указывайте тип компилятора, его версию, а также платформу (Windows/Linux/..) компиляции, другими словами, Target.
Модераторы: volvo877
Страницы: (2) [1] 2  все  ( Перейти к последнему сообщению )  
> напоминающее OWL , Зацените
    Вот накропал об юзаемой мной самоделке. Представляю на обозрение уважаемых колег.
    ExpandedWrap disabled
      unit ow;
      interface
      uses Windows;
       
      Type
         TWindowAttr = record
         Title: PChar;
         Style: Longint;
         ExStyle: Longint;
         X, Y, W, H: Integer;
         Menu:HMenu;
         end;
       
      Pwindow=^TWindow;
      TWindow= object
      HWindow,ParentWindow:HWnd;
      CHief:PWindow;
      wndClass:TwndClass;
      Attr:TwindowAttr;
      constructor Init(PChief:PWindow);
      destructor Done;virtual;
      Function AcceptMessage(Window: HWnd; AMessage :word; WParam, LParam: Longint):longint;virtual;
      procedure Create(HParent:HWnd);virtual;
      end;
       
      procedure runapplication(MainWindow:Pwindow);
      implementation
       
      function WindowProc(Window: HWnd; AMessage :word; WParam,LParam: Longint): longint; stdcall;
      var Pw:Pwindow;
      begin
      if Amessage=wm_create then begin
      pw:=pcreatestruct(Lparam).lpCreateParams;
      pw^.HWindow:=Window;
      setWindowLong(Window,gwl_UserData,longint(pw));
      end;
      pw:=pointer(getwindowlong(window,gwl_Userdata));
      if pw<>nil then windowproc:=pw^.AcceptMessage(Window,Amessage,wparam,lparam)
      else windowProc:=defwindowproc(window,Amessage,wparam,lparam);
      end;
       
      constructor Twindow.init(PChief:PWindow);
      begin
        WndClass.Style := cs_hRedraw or cs_vRedraw;
        WndClass.lpfnWndProc := @WindowProc;
        WndClass.cbClsExtra := 0;
        WndClass.cbWndExtra := 0;
        WndClass.hInstance := HInstance;
        WndClass.hIcon := LoadIcon(0, idi_Application);
        WndClass.hCursor := LoadCursor(0, idc_Arrow);
        WndClass.hbrBackground := color_window;
        WndClass.lpszMenuName := nil;
        wndClass.lpszClassName := 'zenIA';
        attr.Title:='Main Window';
        attr.Style:=ws_visible or ws_overlappedwindow;
        attr.ExStyle:= 0;
        attr.X:=cw_UseDefault;
        attr.Y:=cw_UseDefault;
        attr.w:=cw_UseDefault;
        attr.H:=cw_UseDefault;
        attr.Menu:=0;
        Chief:=PChief;
      end;
       
      destructor TWindow.done;
      begin
      DestroyWindow(HWindow);
      end;
       
      function TWindow.AcceptMessage(Window: HWnd; AMessage :word; WParam, LParam: Longint):longint;
      begin
      AcceptMessage:=0;
      case AMessage of
      wm_destroy:begin postquitmessage(0);exit;end;
      wm_create: begin exit; end;
      end;
      AcceptMessage:=defwindowproc(window,Amessage,wparam,lparam);
      end;
       
      procedure TWindow.Create(HParent:Hwnd);
      var wnd:TWndClass;
      begin
      ParentWindow:=HParent;
      registerClass(wndClass);
      CreatewindowEx(Attr.ExStyle,wndClass.lpszClassName,Attr.Title,attr.style,attr.x,
      attr.y,attr.w,attr.h,ParentWindow,attr.menu,Hinstance,@self);
      end;
       
      procedure runapplication(MainWindow:Pwindow);
      var AMessage:TMsg;
      begin
      MainWindow^.create(0);
      UpdateWindow(MainWindow^.hWindow);
      while GetMessage(AMessage, 0, 0, 0) do begin
      TranslateMessage(AMessage);
      DispatchMessage(AMessage);
      end;
      end;
       
      begin
      end.


    Дабы не изовраться вконец, опускаю большинство теоретических выкладок, касающихся основ работы Винды и начинаю по сути.

    Не много о терминах.
    Под «Оконным объектом» я понимаю объект производный от TWindow, ответственный за работу окна Виндовс, под «Окном Виндовс» я понимаю квадратик с заголовком, выводимый функцией CreateWindowEx J

    Что к чему.
    Мой оконный объект TWindow. Содержит следующие переменные:
    Hwindow:HWnd; — хендл окна Виндовс, управляемого данным оконным объектом;
    ParentWindow:HWnd; — хендл окна Виндовс родительского окна.
    CHief:PWindow;- указатель на оконный объект родительского окна. Данную переменную я использую для вызова метода AcceptMessage родительского объекта, минуя систему сообщений.
    wndClass:TwndClass; - запись, содержащая свойства оконного класса, передаваемая в функцию RegisterClass, подробнее в справочниках по Винде.
    Attr:TwindowAttr – запись, содержащая свойства окна Виндовс, назначение полей соответствует типу, записанному в стандартной OWL;
    Методы объекта
    constructor Init(PChief:PWindow); - конструктор, по умолчанию производит заполнение wndClass и Attr
    destructor Done;virtual; - деструктор.
    Function AcceptMessage(Window: HWnd; AMessage :word; WParam, LParam: Longint):longint;virtual; Главный обработчик сообщений. Вызывается функцией обратного вызова окна Виндовс, связанного с данным оконным объектом.
    procedure Create(HParent:HWnd);virtual;- регистрирует оконный класс и выводит окно Виндовс.
    В юните также находится процедура RunApplication, ответственная за главный цикл работы программы и WindowProc, являющаяся Call Back-функцией окон.

    Примитивное приложение
    ExpandedWrap disabled
      var w:Twindow;
      begin
      w.init(nil);
      w.attr.title:=’Hello Word!’;
      RunApplication(@W);
      end.

    Как оно работает.
    Для работы системы необходим готовый экземпляр производного объекта от tWindow. Процедура runapplication производит выведение окна главного оконного объекта и цикл получения сообщений. Оконная процедура окна (WindowProc) при создании получает указатель на оконный объект, который, будет руководить реакцией на сообщения. Данный указатель сохраняется с помощью функции SetWindowLong.
    При получении сообщения окном его оконная процедура с помощью функции GetWindowLong получает указатель на «свой» оконный объект и вызывает его метод AcceptMessage, передавая ему, полученное сообщение.

    Как с этой самоделкой работать.
    Вопрос конечно, творческий, но в общих чертах так:
    Описать объект производный от tWindow. При необходимости из конструктора поменять свойства окна объекта (если меняете стиль в wndClass, не забудьте также в поле lpszClassName дать классу новое имя). Переопределить метод AcceptMessage, в котором описать реакцию окна на сообщения. Поскольку вопрос принципиальный, то остановлюсь на некоторых моментах. Этот метод должен работать как процедурные функции, т.е. в случае если сообщение не обработано, AcceptMessage должен возвратить DefWindowProc. Кроме этого, если переопределяется объект главного окна, не забудте обработать сообщение wm_destroy. Как минимум вызвать PostQuitMessage, и если надо вызвать деструктор оконного объекта, иначе Ваша программа останется висеть в памяти, не смотря на закрытие окна.

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

    ExpandedWrap disabled
      uses OW, Windows;
       
      type {тип дочернего оконного объекта}
      tChildWindow=object(TWindow)
      constructor Init(pChief:Pwindow);
      function AcceptMessage(Window:HWnd;AMessage:Word;WParam,LParam:longint):longint;virtual;
      end;
       
      constructor tChildWindow.Init(pChief:Pwindow);
      begin
      inherited init(PChief);
      with Attr do
      begin
      Style:=ws_child or ws_visible or ws_dlgframe; {окно является дочерним, видимым и окружено толстой рамкой}
      {далее устанавливаются положение и размеры дочернего окна}
      x:=10;
      y:=10;
      w:=100;
      h:=75;
      end;
      end;
       
      {Функция обработки сообщений}
      function tchildWindow.AcceptMessage(Window:HWnd;AMessage:Word;WParam,LParam:longint):longint;
      begin
      AcceptMessage:=0;
      case Amessage of
      {в ответ на получение сообщения в случае нажатия девой клавиши мыши выводится соответствующее сообщение}
      wm_lButtonDown:begin MessageBox(HWindow,'Вы нажали левую клавишу мыши','Зафиксировано сообщение',mb_iconexclamation);exit;end;
      end;
      AcceptMessage:=DefWindowProc(Window,AMessage,WParam,LParam);
      end;
       
      {тип главного окна окна}
      type
      tMainWindow=object(TWindow)
      Brush:Hbrush; {кисть, которой будет закрашен фон главного окна}
      pChild:^tChildWindow; {указатель на тип дочернего оконного объекта}
      constructor Init(pChief:Pwindow);
      destructor done;virtual;
      function AcceptMessage(Window:HWnd;AMessage:Word;WParam,LParam:longint):longint;virtual;
      end;
       
      constructor tMainWindow.Init(pChief:Pwindow);
      begin
      inherited init(PChief);
      {создаем непрерывную кисть оранжевого цвета}
      Brush:=CreatesolidBrush($00bbff);
      {хендл кисти соответствующему полю переменной wndClass}
      wndClass.hbrBackground:=brush;
      {необходимо изменить имя оконного класса, так как хочется, чтобы иные окна создаваемыми производными от tWindow сохраняли первоначальные свойства (в данном случае серый цвет)}
      wndclass.lpszClassName:='PARENT';
      {изменяем заголовок окна}
      attr.title:='Нас не подолати!';
      {создаем экземпляр оконного объекта дочернего окна}
      New(pChild,init(@self));
      end;
       
      destructor tMainWindow.done;
      begin
      {создаваемые объекты, в том числе и кисти надо убирать после использования}
      deleteobject(Brush);
      {освобождаем память занятую дочерним оконным объектом}
      dispose(pChild,done);
      end;
       
      {Функция обработки сообщений}
      function tMAinWindow.AcceptMessage(Window:HWnd;AMessage:Word;WParam,LParam:longint):longint;
      begin
      AcceptMessage:=0;
      case Amessage of
      {если получено сообщение о создании главного окна создаем и дочернее}
      wm_create:begin pChild.Create(HWindow);exit;end;
      {если получено сообщение о разрушении главного окна, вызываем деструктор оконного объекта и завершаем приложение}
      wm_destroy: begin done; PostQuitMessage(0);exit;end;
      end;
      AcceptMessage:=DefWindowProc(Window,AMessage,WParam,LParam);
      end;
       
      {экземпляр главного оконного объекта}
      var MAinWindow:TMainWindow;
      begin
      MainWindow.init(nil);
      runApplication(@Mainwindow);
      end.


    M
    Женя, следи почаще за своими выражениями!
    Сообщение отредактировано: Romtek -
      ТРЕТЬЯ ЧАСТЬ МАРЛИЗОНСКОГО БАЛЕТА


      Итак, выкладываю третью подверсию.

      Какие внесены дополнения.
      1. Описаны типы для открытых массивов (удобная штука для обращения к динамической памяти): paChar; paWord, paShortIn и т.д.

      2. Предусмотрена возможность работы с немодальными диалоговыми окнами для этого хендлы диалогов записываются в открытый массив HDIALOGS:PALongint переменная NModelessDialogs:bword хранит количество элементов в массиве. Для записи нового элемента используется процедура procedure AddModelessDialog(Window:HWnd); а для удаления — procedure DeleteModelessDialog(Window:HWnd); кроме этого для удобства

      Описаны ряд функций для удобства создания немодальных диалогов с «регистрацией» их:
      function OWCreateDialog(Instance: hInst; TemplateName: PChar; WndParent: hWnd; DialogFunc: TFNDlgProc): hWnd; — аналог CreateDialog
      function OWCreateDialogParam(Instance: hInst; TemplateName: PChar; WndParent: hWnd; DialogFunc: TFNDlgProc; Param: lParam): hWnd; — аналог CreateDialogParam.
      function OWCreateDialogIndirect(Instance: hInst; const Template: TDlgTemplate; WndParent: hWnd; DialogFunc: TFNDlgProc): hWnd; — аналог CreateDialogIndirect.
      function OWCreateDialogIndirectParam(Instance: hInst; const Template: TDlgTemplate; WndParent: hWnd; DialogFunc: TFNDlgProc; Param: lParam): hWnd; — аналог CreateDialogIndirectParam
      А также function DestroyDialog(Wnd: hWnd): Bool; вызывающая для диалога DestroyWindow с удалением хендла данного диалога из массива.

      Обратите внимание !!! Если Вы собираетесь использовать в своей программе немодальные диалоговые окна, используйте для создания цикла обработки сообщений вместо функции RunApplication новую функцию RunApplicationD по синтаксису аналогичную предыдущей. В четвертой версии юнита RunApplication

      3. У объекта TWindow появился потомок TDialogWindow, являющийся гибридом обычного окна и диалога. С пользовательской точки зрения новый тип отличается
      а) наличием поля pRESOURCETEMPLATE:pChar; которое может содержать имя ресурса, содержащего шаблон диалога (при этом необходимо, чтобы имя класса ресурса совпадало со значением WndClass.lpzName). Если это поле не содержит имени ресурса, то окно создается на основании переменной Attr (размеры интерпретируются как данные в логических, а не экранных единицах, а меню придется загрузить вручную).
      б) Если программа использует этот тип окна то, для обработки сообщений необходимо использовать функцию RunApplicationD В четвертой версии юнита RunApplication.
      в) окно не получает wm_create, но получает wm_initdialog.

      Что дальше?
      В следующем обновлении предусмотрю возможность работы с акселераторами, а то не надо было, так и не предусмотрел.
      Сообщение отредактировано: ZenIA -

      Прикреплённый файлПрикреплённый файлSample.zip (10.93 Кбайт, скачиваний: 163)
        У тебя часть заголовка отсутствует в первом исходнике.
          romtek, я все-равно исходников у себя не оставил… :D

          Доброе время суток,
          в систему были внесены следующие изменения:
          Добавлены процедуры
          procedure OnAcceleratorsTable(Window, ACCTABLE:Handle); — подключает систему акселераторов
          Window — хендл окна, который будет принимать события быстрых клавиш.
          ACCTABLE — хендл таблицы акселераторов (например загруженной LoadAccelerators).
          procedure OffAcceleratorsTable; — отключает таблицу акселераторов. Таблица акселераторов никак не изменяется, поэтому выгружать или разрушать ее придется «вручную».

          Удалена процедура RunApplicationD — вместо нее теперь используется обновленная RunApplication.

          Особенности реализации
          Для работы с акселераторами введены 2 внутренние переменные hACCELERATORSTABLE:HACCEL и
          hACCELERATORSWINDOW:HWND в которых сохраняются хендлы таблицы акселераторов и окна, принимающего их сообщения.

          Циклы обработки событий в зависимости от наличия немодальных диалогов и акселераторов записаны в процедурах WindowProcessing, WindowMLDialogProcessing, WindowAcceleratorsProcessing, WindowAcceleratorsMLDialogProcessing ссылки на которые устанавливаются процедурами OnAcceleratorsTable, OffAcceleratorsTable, AddModelessDialog, DeleteModelessDialog

          Пример схожий с предыдущим, но с подключением акселераторов
          uses Windows,OW;
          {$R OW}
          type
          tMeDialogWindow=object(tDialogWindow){Мой объектный тип}
          constructor init(pChief:PWindow);
          function AcceptMessage(Window:HWnd;AMessage:Word;WPARAM,LParam:longint):longint;virtual; {метод обработки сообщений}
          end;

          constructor tMeDialogWindow.init(pChief:PWindow);
          begin
          inherited init(pChief);
          pRESOURCETEMPLATE:='DLG';{Окно будет создано из ресурса}
          end;

          function tMeDialogWindow.AcceptMessage(Window:HWnd;AMessage:Word;WPARAM,LParam:longint):longint;
          begin
          AcceptMessage:=0;
          case AMessage of
          wm_initdialog:
          begin
          OnAcceleratorsTable(Window,LoadAccelerators(Hinstance,'ACC')); {При создании данного окна активируется система обработки сообщений от акселераторов, таблица грузится из ресурса}
          exit;
          end;
          wm_command:
          begin
          case LoWord(WParam) of
          101: destroyWindow(Window);{Если сообщение от кнопки то выходим (101 - идентификатор кнопки из ресурса)}
          102:begin MessageBox(Window,’Внимание окно будет закрыто’,’Нажаты “Горячие клавиши”’,0);destroyWindow(Window);end;{Если сообщение от акселератора перед выходом информируем об этом (102 - идентификатор «горячей клавиши» из ресурса)}
          end;
          exit;
          end;
          WM_Destroy:
          begin
          postQuitMessage(0);
          exit;
          end;
          end;
          AcceptMessage:=DefWindowProc(Window,Amessage,Wparam,Lparam);
          end;

          var w:tMeDialogWindow;
          begin
          w.init(nil);
          RunApplication(@w);
          end.


          Ресурсный файл
          DLG DIALOG 18, 18, 140, 92
          STYLE WS_VISIBLE | WS_OVERLAPPEDWINDOW
          CLASS "DWZENIA"
          CAPTION "DIALOG WINDOW"
          BEGIN
          PUSHBUTTON "ВЫХОД", 101, 10, 65, 120, 15, WS_CHILD | WS_VISIBLE | WS_TABSTOP
          CTEXT "ДЛЯ ВЫХОДА МОЖНО НАЖАТЬ CTRl+END", -1, 8, 7, 125, 50, WS_CHILD | WS_VISIBLE | WS_GROUP
          END


          ACC ACCELERATORS
          BEGIN
          VK_END, 102, VIRTKEY, CONTROL
          END
          Сообщение отредактировано: ZenIA -

          Прикреплённый файлПрикреплённый файлSample.zip (8.89 Кбайт, скачиваний: 159)
            Ну все последнее-распоследнее усовершенствованице…
            в tWindow и tDialogWindow введено поле isMainWindow:boolean, при установке которого в TRUE закрытие данного окна вызывает завершение приложения (что и делает функция runApplication), таким образом теперь при разрушении окна объекта, передаваемого runApplication, работа цикла обработки сообщений прекращается без дополнительной обработки в методе AcceptMessage.
            Сообщение отредактировано: ZenIA -
              Я убрал все лишнее из метода AcceptMessage в прошлой версии.
              А теперь немного о конвенциях. Я предлагаю создавать компоненты следующим образом:
              Когда Вы хотите в дочернем оконном типе обработать новые сообщения wm_message1 wm_message2 Вы
              1. Описываете новые методы по типу:
              Function wmmessage1 (wParam,Lparam:longint):longint;virtual;
              Function wmmessage2 (wParam,Lparam:longint):longint;virtual;
              , в которых вы определяете реакцию на сообщение.
              2. переопределяете метод AcceptMessage следующим образом

              function TWindow.AcceptMessage(Window: HWnd; AMessage :word; WParam, LParam: Longint):longint;
              begin
              CASE Amessage OF
              wm_Message1: AcceptMessage:=wmmessage1 (wParam ,Lparam);
              wm_Message2: AcceptMessage:=wmmessage2 (wParam ,Lparam);
              ELSE AcceptMessage:=inherited AcceptMessage (Window, Amessage, WParam, LParam);
              end;


              И в конце добью последним примером — выводится окно с дочерним

              uses OW,Windows;

              type {Дочернее окно}
              PChildWindow=^TChildWindow;
              TChildWindow=object(TWINDOW)
              constructor init(pChief:pWindow);
              function AcceptMessage(Window: HWnd; AMessage :word; WParam, LParam: Longint):longint;virtual; {метод должен вызывать метод обработки события wm_paint}
              function WMPAINT(WPARAM,LPARAM:Longint):longint;virtual; {окно будет по-особенному перересовываться}
              end;


              constructor tChildWindow.init(pChief:pWindow);
              begin
              inherited init(pChief);
              wndClass.lpszClassName:='CHILD'; {мы хотим изменить свойство класса окна и потому класс должен быть перергистрирован под новым именем}
              wndClass.hbrBackground:=createSolidBrush($aa00); {фон у окна будет зеленым}
              Attr.Style:=ws_child or ws_visible or ws_thickframe; {это будет видимое дочернее окно с толстой рамкой}
              end;


              function tChildWindow.AcceptMessage(Window: HWnd; AMessage :word; WParam, LParam: Longint):longint;
              begin
              Case AMessage of
              WM_Paint:WMPAINT(WPARAM, LPARAM); {для перерисовки вызывается метод WMPAINT }
              ELSE TWINDOW.ACCEPTMESSAGE(WINDOW,AMESSAGE,WPARAM,LPARAM);
              end;
              end;

              function tChildWindow.WMPAINT(WPARAM,LPARAM:Longint):longint; {пишем текст при помощи } DRAWTEXT
              var dc:HDC;TPS:TPAINTSTRUCT;tr:TRect;
              begin
              dc:=BeginPaint(HWindow,TPS);
              GetClientRect(HWindow,TR);
              setbkMode(dc,transparent);
              DRAWTEXT(dc,'Hello World',11,tr,dt_center or dt_vcenter or dt_singleline);
              EndPaint(HWindow,TPS);
              end;

              type {А это оконный объект главного окна}
              tNewWindow=object(tWindow)
              Child:tChildWindow; {наше дочернее окно}
              function AcceptMessage(Window: HWnd; AMessage :word; WParam, LParam: Longint):longint;virtual;
              function WMCREATE(WPARAM,LPARAM:Longint):longint;virtual;{Это лучшее место для создания дочерних окон}
              end;

              function tNewWindow.WMCREATE(WPARAM,LPARAM:Longint):longint;
              var tr:trect;
              begin
              GetClientRect(hWindow,tr);
              Child.init(@self); {инициализация дочернего оконного объекта}
              {Эти свой ства не возможно было установить при инициализации дочернего оконного объека}
              Child.Attr.x:=getSystemMetrics(sm_cyCaption);
              Child.Attr.y:=Child.Attr.x;
              Child.Attr.W:=tr.right-Child.Attr.x shl 1;
              Child.Attr.H:=tr.Bottom-Child.Attr.x shl 1;
              Child.Create(hWindow); {создание дочернего оконного объекта}
              deleteobject(Child.wndclass.hbrBackground); {странно, но с этой командой тоже работает J}
              wmCreate:=0;
              end;

              function tNewWindow.AcceptMessage(Window: HWnd; AMessage :word; WParam, LParam: Longint):longint;
              begin
              Case AMessage of
              wm_Create: ACCEPTMESSAGE:=WMCREATE(WPARAM, LPARAM);{в ответ на получение сообщения о создании собственного окна вызываем WMCREATE, создающий окно дочернего объекта}
              else acceptMessage:=inherited AcceptMessage(Window,AMessage,WParam,LParam);
              end;
              end;

              var TNW:TNEWWINDOW; {экземпляр главного окна}
              begin
              TnW.init(nil);
              runApplication(@TnW); {процедура обеспечивающая прием и диспетчеризацию сообщений}
              end.
              Сообщение отредактировано: ZenIA -
                Привет всем.
                Спешу и падаю сообщить о внесении изменений в модуль OW.pas.
                С пользовательской точки зрения важно следующее:
                1 .У типа tDialogWindow появился метод procedure Exec(HParent:HWnd);virtual;, выводящий окно в ввиде модального диалога.
                2. У него же появилось свойство isModal:boolean; равняющееся ИСТИНА если окно выведено как модальное. НЕ ИЗМЕНЯЙТЕ ЗНАЧЕНИЕ ЭТОГО СВОЙСТВА.
                3. У этого же типа появился виртуальный метод Close, вызываемый если пользователь пытается закрыть окно (пользуясь системным меню, нажимая на крестик или, нажмая на клавиатуре Alt+F4). Переопределяя этот метод можно отменить закрытие окна, например, чтобы спросить о необходимости сохранится.
                4 Там же. Добавлено свойство DefProc:tAcceptMessage оно содержит указатель на процедуру умолчательной обработки мессаги. НЕ ИЗМЕНЯЙТЕ ЕГО.
                5. Облегчено создание окон из диалога без указания имени класса.
                6. Предусмотрен случай создания экземпляром оконного класса, окна Виндовс при уже имеющемся. В этом случае существующее окно уничтожается.

                КОД МОДУЛЯ OW см. ДАЛЕЕ в СООБЩЕНИЯХ

                В заключении пример, иллюстрирующий новые возможности.
                Сообщение отредактировано: ZenIA -

                Прикреплённый файлПрикреплённый файлsample.zip (20.98 Кбайт, скачиваний: 149)
                  Да пожалуйста, хотя сами ратовали за применения тегов [CODE] :)
                  Облегчено создание диалоговых окон внутри DLL. Введено новое поле объекта tDialogWindow — hResourceInstance, которое используется для вызова диалогов используется в качестве Instance.

                  Для примера описана функция ModalDialogWindow описанная в Server.dll, воспринимающая хендл родительского окна и выводящая модальный диалог.
                  library Server;
                  {$R Server.res}
                  uses OW,Window;
                  {$R Resource}
                  function ShowModalDialog(Window.HWnd):stdcall;export;
                  var ModalDialogWindow: tDialogWindow
                  begin
                  ModalDialogWindow.init(nil);
                  ModalDialogWindow.hResourceInstance:=GetModuleInstance('Server.dll');
                  ModalDialogWindow.pResoucetemplate:='DLG_MAIN';
                  ModalDialogWindow.Exec(Window);
                  end;

                  exports ModalDialogWindow name 'ModalDialogWindow';
                  begin
                  end.

                  Ресурсный файл server.rc

                  DLG_MAIN DIALOG 18, 18, 154, 112
                  STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
                  CAPTION "MODAL DIALOG"
                  CCLASS "DWZENIA"
                  BEGIN
                  LTEXT "Я МОДАЛЬНЫЙ ДИАЛОГ", -1, 1, 1, 150, 110, WS_CHILD | WS_VISIBLE | WS_GROUP
                  END

                  Цепляю к сообщению последнюю версию модуля OW.
                  Сообщение отредактировано: ZenIA -

                  Прикреплённый файлПрикреплённый файлOW.pas (14.01 Кбайт, скачиваний: 245)
                    Теперь система поддерживает MDI

                    Дополнена цепочка обработки сообщений. Теперь оконная процедура (не предназначена для модификации) вызывает для обработки сообщения метод function PreProc(Window: HWnd; AMessage :word; WParam, LParam: Longint):boolean;virtual;, если данный метод возвращает TRUE, для обработки вызывается метод Function AcceptMessage. Это нововведение — для создания производных типов. Например, если Вы хотите создать окно с анимацией, Вы можете создать таймер, по сообщению которого будут сменяться кадры анимации, обрабатывать их в методе PreProc и возвращать FALSE, таким образом, для программистов, использующих Ваш класс, отпадет кусок работы.

                    Для создания MDI-приложений в юните OW предопределены новые типы

                    Оконный тип дочернего окна MDI.
                    tMDIChildWindow=object(tWindow)
                    constructor Init(PChief:PWindow);
                    procedure Create(HParent:HWnd);virtual;
                    Function AcceptMessage(Window: HWnd; AMessage :word; WParam, LParam: Longint):longint;virtual;
                    function PreProc(Window: HWnd; AMessage :word; WParam, LParam: Longint):boolean;virtual;
                    end;


                    NB 1. Родителем данного окна передаваемого в конструктор, может быть только тип tFrameWindow или его наследник. Параметр Hparent метода Create игнорируется (в методе используется hMDIClient родительского оконного объекта)
                    2. Данный тип должен быть динамическим и создаваться функцией или процедурой New,


                    Коллекция pMDIChildWIndow
                    tMDICollection=object
                    Count:Word; - количество элементов
                    Items:papMDIChildWIndow; - динамический массив элементов
                    Constructor Init;
                    Destructor Done;
                    Function FindItem(Item:pMDIChildWIndow):integer; - поиск элемента в коллекции
                    Function Add(Item:pMDIChildWIndow):word; - добавление элемента
                    Procedure Delete(n:word); - удаление элемента
                    Function GetItem(n:Word):pMDIChildWindow; - получение элемента
                    end;



                    Окнный объект главного MDI-окна

                    pFrameWindow=^tFrameWindow;
                    {$I d:\projects\basis\COLLECTION1.INC}
                    tFrameWindow=object(tWindow)
                    hMDIClient:hWnd; - хендл окна-клиента
                    hMenuChilds:hMenu; - Popup-меню, куда будут добавляться названия создаваемых дочерних окон
                    idFirstChild:word; - идентификатор первого дочернего окна, следующим окнам будут присваивается следующие по порядку номера (идентификатор пересылается с сообщением wm_command, если пользователь, щелкнул по заголовку данного окна)
                    ChildsCollection:tMDICollection; - колекция указателей на дочерние окна.
                    ActiveChild:Pointer; — указатель на активное дочернее окно.
                    procedure Cascade; — упорядочивает дочерние окна.
                    procedure HorizontalTile; — упорядочивает дочерние окна.
                    procedure VerticalTile;— упорядочивает дочерние окна.
                    constructor Init(PChief:PWindow);
                    destructor Done;virtual;
                    Function AcceptMessage(Window: HWnd; AMessage :word; WParam, LParam: Longint):longint;virtual;
                    function PreProc(Window: HWnd; AMessage :word; WParam, LParam: Longint):boolean;virtual;
                    end;


                    Да, чуть не забыл напомнить об особенности Windows — некоторые сообщения должны передаваться на умолчательную обработку. Если Вы не помните какие, то воспользуйтесь функцией Function IsDefaultMessage(Window:byte;AMessage:word):boolean;, где Window может быть константами idMDIFrame и idMDIChild, а Amessage — номер сообщения. Функция возвращает True, если данное сообщение должно быть обработано по умолчанию.
                    Сообщение отредактировано: ZenIA -
                      Женя, сходи на Вики. Там статьи лучше писать. И про обрамление тегами не забывай. ;)
                        Низко берете, коллега, не меньше книги!!!
                        На подходе еще ActiveX-контейнеры ;) Система пока не только сырая, но и подчастую незаконченная…
                        Сообщение отредактировано: ZenIA -
                          Кажись топик тонет...
                          Обновленная версия. Пришлось возвратить сохранение ссылки на объект tDialogWindow через SetWindowLong, дабы вернуть возможность создавать диалоги предопределенного системой класса (напомню, что это происходит если в ресурсе диалога не указано имя класса).
                          Да и как-то забыл, что уже давненько положение и размеры окна tDialogWindow выражаются в пикселях, а не логических единицах.
                          Прикреплённый файлПрикреплённый файлOW.zip (5.13 Кбайт, скачиваний: 146)
                            ZenIA, а тонет этот топик по той причине, что никому не нужен WinAPI. Если кому нужны окна, использует или OWL, или KOL/другие библиотеки для Дельфи/Free Pascal.
                              Цитата Romtek @
                              ZenIA, а тонет этот топик по той причине, что никому не нужен WinAPI.

                              5 баллов !!!! :D
                                ZenIA, а ты докажи, что я не прав. ;)
                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                0 пользователей:


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,0568 ]   [ 16 queries used ]   [ Generated: 26.03.23, 08:50 GMT ]