Текущий архив: 2005.02.20;
Скачать: CL | DM;
ВнизПроблема с выводом изображения на канву формы... Найти похожие ветки
← →
Artemka © (2004-10-26 21:33) [0]Здравствуйте! Нужна помощь... Из почти тривиальной задачи выросла проблема, которую я никак не могу решить! :) Ответа я не найти не могу, так что надеюсь на вашу помощь.
Значит, так: требуется перемещать (как-то) маленькое изображение по форме. Для обеспечения плавного движения я использовал мультимедийный таймер. В обработчике сообщений этого таймера изображение рисуется сначала на канве bitmap"а, а потом копируется на канву формы приложения. И вот тут то возникает странное (для меня) явление: если не двигать мышь, то все нормально... но стоит только начать двигать мышь, и через некоторое время (оно тем меньше, чем меньше задержка у таймера) объект перестает двигаться, хотя таймер не останавливается и приложение нормально реагирует на события. Рисование объекта на форме возобновляется, если вызывается событие OnPaint (если свернуть и потом развернуть форму, например). Дальше все опять повторяется. Кто подскажет в чем дело?
P.S. Может мышь, конечно, и не причем... :)
← →
Kind (2004-10-26 21:52) [1]У меня было нечто похожее, когда таймер срабатывает чаще, чем успевает перерисоваться всё окно, т.е. OnPaint ещё не отработан а у тебя уже следующий тик таймера. Хотя ...
У тебя OnIdle не задействован?
← →
Artemka © (2004-10-26 22:08) [2]У меня такие же подозрения. Я только не могу понять: почему на мышь такая реакция?!
Насчет OnIdle - нет. Я его вообще ни разу в жизни не пробовал...
← →
Mihey_temporary © (2004-10-26 22:30) [3]Видать, перемудрил...
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-27 01:51) [4]Спасибо за помощь! Действительно, перемудрил... :-) Правда суть вышеописанного мной "бага" мне так и не ясна. Бы очень рад удовлетворить свое любопытство! Так что если кто знает...
← →
debuger © (2004-10-27 16:02) [5]Расскажи о мультимедийном таймере и способе его использования.
← →
Artemka © (2004-10-27 20:52) [6]Мультимедийный таймер может имееть период срабатывания от 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";
← →
Kind (2004-10-27 21:55) [7]Выложи код, посмотрим при чём тут мышка.
← →
Sapersky (2004-10-28 10:15) [8]но стоит только начать двигать мышь, и через некоторое время (оно тем меньше, чем меньше задержка у таймера) объект перестает двигаться
Если это WinXP - то там, похоже, обработка мыши какая-то очень навороченная. У меня тоже был случай, когда из-за мыши тормозило, хотя таймером не пользовался, а рисовал в основном цикле WinAPI (примерно то же самое, что и OnIdle c Done=False) и делал паузу Sleep.
← →
Artemka © (2004-11-05 01:35) [9]Был вынужден долго отсутствовать... :-) Думаю в исходниках потребности нет, т.к. взглянув трезвым взглядом на чудо-прогу, я счел ее слишком кривой и переписал. Дело в том, что когда имел место вышеописанный мною галюн, я поступал так:
1) в обработчике таймера (если установлен флаг) вызывал процедуру перерисовки;
2) в этой процедуре экран перерисовывался в буфере (TBitmap) и только потом выводился на канву формы.
(Самому плохо что-то стало от такого... :))
Потом я прозрел и в обработчике таймера вставил процедуру Invalidate, а всю перерисовку сунул в OnPaint (используя DoubleBuffered = true). Ну и злополучная мышинная аномалия исчезла... Все...
Так что спасибо всем за внимание. Вопрос, я думаю, исчерпан. :-) (дело было в кривости моих рук :))
Страницы: 1 вся ветка
Текущий архив: 2005.02.20;
Скачать: CL | DM;
Память: 0.47 MB
Время: 0.042 c