![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Проблема с выводом изображения на канву формы... [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 не задействован?