Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Проблема с выводом изображения на канву формы... [D6, WinXP]


Artemka ©   (2004-10-26 21:33:00) 

Здравствуйте! Нужна помощь... Из почти тривиальной задачи выросла проблема, которую я никак не могу решить! :) Ответа я не найти не могу, так что надеюсь на вашу помощь.
Значит, так: требуется перемещать (как-то) маленькое изображение по форме. Для обеспечения плавного движения я использовал мультимедийный таймер. В обработчике сообщений этого таймера изображение рисуется сначала на канве bitmap'а, а потом копируется на канву формы приложения. И вот тут то возникает странное (для меня) явление: если не двигать мышь, то все нормально... но стоит только начать двигать мышь, и через некоторое время (оно тем меньше, чем меньше задержка у таймера) объект перестает двигаться, хотя таймер не останавливается и приложение нормально реагирует на события. Рисование объекта на форме возобновляется, если вызывается событие OnPaint (если свернуть и потом развернуть форму, например). Дальше все опять повторяется. Кто подскажет в чем  дело?
P.S. Может мышь, конечно, и не причем... :)


Artemka   (2004-11-05 01:35:00) [1]

Был вынужден долго отсутствовать... :-) Думаю в исходниках потребности нет, т.к. взглянув трезвым взглядом на чудо-прогу, я счел ее слишком кривой и переписал. Дело в том, что когда имел место вышеописанный мною галюн, я поступал так:
1) в обработчике таймера (если установлен флаг) вызывал процедуру перерисовки;
2) в этой процедуре экран перерисовывался в буфере (TBitmap) и только потом выводился на канву формы.
(Самому плохо что-то стало от такого... :))
Потом я прозрел и в обработчике таймера вставил процедуру Invalidate, а всю перерисовку сунул в OnPaint (используя DoubleBuffered = true). Ну и злополучная мышинная аномалия исчезла... Все...

Так что спасибо всем за внимание. Вопрос, я думаю, исчерпан. :-) (дело было в кривости моих рук :))


Sapersky   (2004-10-28 10:15:00) [2]

но стоит только начать двигать мышь, и через некоторое время (оно тем меньше, чем меньше задержка у таймера) объект перестает двигаться

Если это WinXP - то там, похоже, обработка мыши какая-то очень навороченная. У меня тоже был случай, когда из-за мыши тормозило, хотя таймером не пользовался, а рисовал в основном цикле WinAPI (примерно то же самое, что и OnIdle c Done=False) и делал паузу Sleep.


Kind   (2004-10-27 21:55:00) [3]

Выложи код, посмотрим при чём тут мышка.


Artemka   (2004-10-27 20:52:00) [4]

Мультимедийный таймер может имееть период срабатывания от 1 мс и выше. Однако этот таймер не имеет компонентного воплощения, поэтому для доступа к нему приходится использовать функции API.

Обработчик для таймера, например, такой:


procedure TimeProc(uID, uMsg: UINT; dwUser, dw1, dw2: DWORD); stdcall;  


Запуск и выключение таймера реализуется функциями, импортируемыми из библиотеки "winmm.dll":


function timeSetEvent(uDelay, uResolution: UINT; lpTimeProc: Pointer; dwUser: DWORD; fuEvent: UINT): UINT; stdcall; external 'winmm.dll';

function timeKillEvent(uID: UINT): UINT; stdcall; external 'winmm.dll';  


debuger   (2004-10-27 16:02:00) [5]

Расскажи о мультимедийном таймере и способе его использования.


Artemka   (2004-10-27 01:51:00) [6]

Спасибо за помощь! Действительно, перемудрил... :-) Правда суть вышеописанного мной "бага" мне так и не ясна. Бы очень рад удовлетворить свое любопытство! Так что если кто знает...


Mihey_temporary   (2004-10-26 22:30:00) [7]

Видать, перемудрил...


unit mainUnit;

interface

uses
 Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;

type
 TmainForm = class(TForm)
   procedure FormCreate(Sender: TObject);
   procedure FormDestroy(Sender: TObject);
   procedure FormMouseDown(Sender: TObject; Button: TMouseButton;
     Shift: TShiftState; X, Y: Integer);
   procedure FormMouseUp(Sender: TObject; Button: TMouseButton;
     Shift: TShiftState; X, Y: Integer);
   procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X,
     Y: Integer);
   procedure FormPaint(Sender: TObject);
 private
   { Private declarations }
 public
   procedure IdleHandler(Sender: TObject; var Done: Boolean);
 end;

var
 mainForm: TmainForm;
 Bmp: TBitmap;
 x0, y0, w0, h0: Integer;
 Dragginn: Boolean;

implementation

{$R *.DFM}

procedure TmainForm.IdleHandler(Sender: TObject; var Done: Boolean);
begin
 Invalidate;
end;

procedure TmainForm.FormCreate(Sender: TObject);
begin
 Bmp := TBitmap.Create;
 Bmp.LoadFromFile('bitmap.bmp');
 w0 := Bmp.Width; h0 := Bmp.Height;
 x0 := 50; y0 := 50;
 DoubleBuffered := True;
 Application.OnIdle := IdleHandler;
end;

procedure TmainForm.FormDestroy(Sender: TObject);
begin
 Bmp.Free;
end;

procedure TmainForm.FormMouseDown(Sender: TObject; Button: TMouseButton;
 Shift: TShiftState; X, Y: Integer);
begin
 If PtInRect(Rect(x0,y0,x0+w0,y0+h0), Point(X,Y)) then
  begin
   Dragginn := True;
   Caption := 'mainForm Draging';
   x0 := X;
   y0 := Y;
  end;
end;

procedure TmainForm.FormMouseUp(Sender: TObject; Button: TMouseButton;
 Shift: TShiftState; X, Y: Integer);
begin
 Dragginn := False;
 Caption := 'mainForm';
end;

procedure TmainForm.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
 Y: Integer);
begin
 If Dragginn then
  begin
    x0 := X;
    y0 := Y;
  end;
end;

procedure TmainForm.FormPaint(Sender: TObject);
begin
 BitBlt(Canvas.Handle, 0, 0, ClientWidth, ClientHeight, Canvas.Handle, 0, 0,
   WHITENESS);
 BitBlt(Canvas.Handle, x0, y0, w0, h0, Bmp.Canvas.Handle, 0, 0, SRCCOPY);
end;

end.


Простое решение с OnIdle.


Artemka   (2004-10-26 22:08:00) [8]

У меня такие же подозрения. Я только не могу понять: почему на мышь такая реакция?!
Насчет OnIdle - нет. Я его вообще ни разу в жизни не пробовал...


Kind   (2004-10-26 21:52:00) [9]

У меня было нечто похожее, когда таймер срабатывает чаще, чем успевает перерисоваться всё окно, т.е. OnPaint ещё не отработан а у тебя уже следующий тик таймера. Хотя ...
У тебя OnIdle не задействован?


Наверх

Титульная страница Поиск, карта сайта Написать письмо