Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 17.11.2016, 09:18   #1
BLACK_RAIN
Форумчанин
 
Регистрация: 13.02.2012
Сообщений: 867
По умолчанию рисование на форме функциями WinAPI

Здравствуйте.
Есть класс, написанный на WinAPI. Он создаёт и закрашивает несколько статиков.
Необходимо подключить этот класс к проекту с формой. Проблема в том, что форма перекрывает его функции рисования.

юнит класса:
Код:

unit UnitClass;

interface

uses Winapi.Windows;

type
  ttestClass = class(TObject)
  public
    nLeft : Integer;
    nTop : Integer;
    nWidth : Integer;
    nHeight : Integer;
    fRoot : HWND;
    fCap :HWND;
    fPanel : HWND;
    fResizer : HWND;
  dc1, dc2, dc3, dcPanel : HDC;
  brush1, brush2, brush3 , brushPanel : HBRUSH;
    OldX : SmallInt;
    OldY : SmallInt;
    OldW : SmallInt;
    OldH : SmallInt;
    drag : Boolean;
    constructor Create(x,y : SmallInt; prt : HWND);
    destructor Destroy; override;
    procedure SetPositionLeft(const x : Integer);
    procedure SetPositionWidth(const w : Integer);
    procedure SetPositionHeight(const h : Integer);
    procedure SetPositionTop(const y : Integer);
    procedure SetPlayerPositionSize(const x,y,w,h : Integer);
    procedure Resize;
    procedure Draw;
    property Left: Integer read nLeft write SetPositionLeft;
    property Top: Integer read nTop write SetPositionTop;
    property Width: Integer read nWidth write SetPositionWidth;
    property Height: Integer read nHeight write SetPositionHeight;
  end;

implementation

constructor ttestClass.Create(x,y: SmallInt; prt : HWND);
begin
  nLeft := x;
  nTop := y;
  nWidth := 200;
  nHeight := 300;
  fRoot := CreateWindowEx(WS_EX_CLIENTEDGE,'static','',
            WS_CHILD or WS_VISIBLE or SS_NOTIFY or SS_BITMAP or WS_CLIPSIBLINGS,
                     x,y, nWidth,nHeight, prt, 0,HInstance,nil);
  fCap := CreateWindowEx(WS_EX_CLIENTEDGE,'static','',
                         WS_CHILD or WS_VISIBLE or SS_NOTIFY or SS_BITMAP,
                     0,0, 0,0, fRoot, 0,HInstance,nil);
  fPanel := CreateWindowEx(WS_EX_CLIENTEDGE,'static','',
                      WS_CHILD    or WS_VISIBLE or SS_NOTIFY or SS_BITMAP,
                     0,0, 0,0, fRoot, 0,HInstance,nil);
  fResizer := CreateWindowEx(WS_EX_CLIENTEDGE,'static','', WS_CHILD or WS_VISIBLE or SS_NOTIFY or SS_BITMAP,
                     0,0, 0,0, fPanel, 0,HInstance,nil);
  dc1 := GetDC(fRoot);
      brush1 := CreateSolidBrush(RGB(0,0,0));
  dc2 := GetDC(fCap);
  brush2 := CreateSolidBrush(RGB(255,0,0));
  dc3 := GetDC(fResizer);
  brush3 := CreateSolidBrush(RGB(0,255,0));

  dcPanel := GetDC(fPanel);
  brushPanel := CreateSolidBrush(RGB(255,0,255));
end;

destructor ttestClass.Destroy;
begin
  ReleaseDC(fRoot,dc1);
  ReleaseDC(fCap,dc2);
  ReleaseDC(fResizer,dc3);
  ReleaseDC(fPanel,dcPanel);

  DeleteObject(brush1);
  DeleteObject(brush2);
  DeleteObject(brush3);
  DeleteObject(brushPanel);

  DestroyWindow(fResizer);
  DestroyWindow(fPanel);
  DestroyWindow(fCap);
  DestroyWindow(fRoot);
  inherited;
end;


procedure ttestClass.SetPlayerPositionSize(const x,y,w,h : Integer);
begin
  nLeft := x;
  nTop := y;
  nWidth := w;
  nHeight := h;
  SetWindowPos(fRoot,0,x,y,w,h, SWP_NOZORDER);
  Resize;
  Draw;
end;

procedure ttestClass.SetPositionLeft(const x : Integer);
begin
  if nLeft <> x then
  begin
    nLeft := x;
    SetPlayerPositionSize(nLeft,nTop,nWidth,nHeight);
  end;
end;

procedure ttestClass.SetPositionTop(const y : Integer);
begin
  if nTop <> y then
  begin
  nTop := y;
  SetPlayerPositionSize(nLeft,nTop,nWidth,nHeight);
  end;
end;

procedure ttestClass.SetPositionWidth(const w : Integer);
begin
  if nWidth <> w then
  begin
  nWidth := w;
  SetPlayerPositionSize(nLeft,nTop,nWidth,nHeight);
  end;
end;

procedure ttestClass.SetPositionHeight(const h : Integer);
begin
  if nHeight <> h then
  begin
  nHeight := h;
  SetPlayerPositionSize(nLeft,nTop,nWidth,H);
  end;
end;

procedure ttestClass.Resize;
var
  r : TRect;
begin
  SetWindowPos(fCap,0,0,0,nWidth,30, SWP_NOZORDER);
  SetWindowPos(fPanel,0,0,nHeight-70,nWidth,70, SWP_NOZORDER);
  GetClientRect(fPanel,r);
  SetWindowPos(fResizer,0, r.Right-30,r.Bottom-30,26,26,SWP_NOZORDER);
end;

procedure ttestClass.Draw;
var
  r : TRect;
begin
  GetClientRect(fRoot,r);
  FillRect(dc1,r,brush1);
  GetClientRect(fCap,r);
  FillRect(dc2,r,brush2);
  GetClientRect(fPanel,r);
  FillRect(dcPanel,r,brushPanel);
  GetClientRect(fResizer,r);
  FillRect(dc3,r,brush3);
end;

end.
Юнит формы:
Код:
unit Unit3;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, UnitClass;

type
  TForm3 = class(TForm)
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure FormPaint(Sender: TObject);
    procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
    procedure FormResize(Sender: TObject);
  private
    { Private declarations }
    procedure OnMax(var msg : TMessage); message WM_SYSCOMMAND;
  public
    { Public declarations }
  end;

var
  Form3: TForm3;
  pl : ttestClass;

implementation

{$R *.dfm}

procedure TForm3.FormCreate(Sender: TObject);
begin
  pl := ttestClass.Create(0,0,Handle);
end;

procedure TForm3.FormDestroy(Sender: TObject);
begin
  pl.Free;
end;

procedure TForm3.FormKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  Close;
end;

procedure TForm3.FormPaint(Sender: TObject);
begin
  pl.Draw;
end;

procedure TForm3.FormResize(Sender: TObject);
begin
  pl.SetPlayerPositionSize(0,0,Width-40,Height-40);
end;

procedure TForm3.OnMax(var msg: TMessage);
begin
  inherited;
  case msg.wParam of
    SC_MAXIMIZE:
    begin
      pl.Draw;
    end;
  end;

end;
end.
При изменении размеров формы, всё рисуется, в целом, нормально (хоть и не без проблем). Но при нажатии кнопки "развернуть"
или при даблклике по заголовку формы окно разворачивается, но закрашивается только
область (0,0,w,h). W/h это ширина и высота окна до разворачивания. Скриншот прикрепил.
Если проходить дебаггером метод Draw(), то всё нормально рисуется. А потом хрясь по F9 и вот что остаётся:

Это можно как-то победить?
И при запуске тоже ничего не рисует. Чтобы нарисовало, надо размер формы дёрнуть.
Переписывать всё на VCL - не советуйте. Класс слишком большой и уже отдебаженный. А то что выше это только пример.
BLACK_RAIN вне форума Ответить с цитированием
Старый 17.11.2016, 12:08   #2
Pavia
Лис
Старожил
 
Аватар для Pavia
 
Регистрация: 18.09.2015
Сообщений: 2,409
По умолчанию

Код:
procedure TForm3.FormCreate(Sender: TObject);
begin
  pl := ttestClass.Create(0,0,Handle);
  repaint;
end;

procedure TForm3.FormResize(Sender: TObject);
begin
  pl.SetPlayerPositionSize(0,0,Width-40,Height-40);
  repaint;
end;
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
У дзен программиста программа делает то что он хотел, а не то что он написал .
Pavia вне форума Ответить с цитированием
Старый 17.11.2016, 12:18   #3
BLACK_RAIN
Форумчанин
 
Регистрация: 13.02.2012
Сообщений: 867
По умолчанию

Цитата:
Сообщение от Pavia Посмотреть сообщение
...
но ведь метод SetPlayerPositionSize() и так сам вызывает функции рисования - метод Draw()
какой еще repaint?
BLACK_RAIN вне форума Ответить с цитированием
Старый 17.11.2016, 13:50   #4
Pavia
Лис
Старожил
 
Аватар для Pavia
 
Регистрация: 18.09.2015
Сообщений: 2,409
По умолчанию

BLACK_RAIN
А у вас Delphi 10. Просто в Delphi 7 и так всё работает. Сейчас в 10 не могу проверить
Попробуйте отключить двойной буфер, там они его изменили.
http://docwiki.embarcadero.com/Libra...DoubleBuffered
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
У дзен программиста программа делает то что он хотел, а не то что он написал .
Pavia вне форума Ответить с цитированием
Старый 17.11.2016, 14:13   #5
BLACK_RAIN
Форумчанин
 
Регистрация: 13.02.2012
Сообщений: 867
По умолчанию

Цитата:
Сообщение от Pavia Посмотреть сообщение
BLACK_RAIN
А у вас Delphi 10. Просто в Delphi 7 и так всё работает. Сейчас в 10 не могу проверить
Попробуйте отключить двойной буфер, там они его изменили.
http://docwiki.embarcadero.com/Libra...DoubleBuffered
то есть, так?
Код:

procedure TForm3.FormCreate(Sender: TObject);
begin
   Form3.DoubleBuffered := False;
  pl := ttestClass.Create(0,0,Handle);
end;
Пропали глюки при ресайзе. А при разворачивании та же хрень.
BLACK_RAIN вне форума Ответить с цитированием
Старый 17.11.2016, 20:05   #6
Pavia
Лис
Старожил
 
Аватар для Pavia
 
Регистрация: 18.09.2015
Сообщений: 2,409
По умолчанию

У меня вот так работает на 10
Код:
procedure TForm1.FormResize(Sender: TObject);
begin
  pl.SetPlayerPositionSize(0,0,Width-40, Height-40);
  Application.ProcessMessages;
  repaint;
end;
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
У дзен программиста программа делает то что он хотел, а не то что он написал .
Pavia вне форума Ответить с цитированием
Старый 18.11.2016, 08:22   #7
BLACK_RAIN
Форумчанин
 
Регистрация: 13.02.2012
Сообщений: 867
По умолчанию

Спасибо, всё прекрасно работает.
BLACK_RAIN вне форума Ответить с цитированием
Старый 18.11.2016, 08:40   #8
BLACK_RAIN
Форумчанин
 
Регистрация: 13.02.2012
Сообщений: 867
По умолчанию

точнее не всё, а почти всё.
Теперь в тестовом примере всё идеально, а в рабочем проекте после F9 форма перекрывает отрисовку не всех статиков, а только некоторых.
Но, возможно, надо со стилями поиграться.
BLACK_RAIN вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
калькулятор на c++ с функциями winapi DreamForse Win Api 6 26.02.2014 14:51
Калькулятор на с++ с функциями WinApi DreamForse Win Api 1 25.02.2014 14:37
Winapi и работа с функциями браузера Dexter_ Win Api 4 25.08.2012 15:41
Открытие файла функциями WinApi virtuhay266 Помощь студентам 1 27.11.2010 21:39
Рисование на форме созданной на WinApi N!ckeL Win Api 3 30.04.2008 19:02