Delphi Paintbox Paint method is not updating image canvas[FMX] - firemonkey

I am working cross platform vnc project. Windows side is ok with VCL. But when i use FMX platform with same code, i having problems.
procedure TFrmScreenView.pbViewPaint(Sender: TObject);
begin
Client.DrawBitmap(pbView.Canvas);
end;
This code is updating to Paintbox Canvas for every new image packet from remote computer. This working on VCL no problem. But when i execute this project on FMX image repaint is not working. It just gets the first image and it doesn't update.
procedure TFrmScreenView.pbViewPaint(Sender: TObject; Canvas: TCanvas);
begin
Client.DrawBitmap(pbView.Canvas);
end;
Client Code:
procedure TClient.DrawBitmap(Canvas: TCanvas);
begin
if assigned(Bitmap) then // Bitmap is global variable
begin
Canvas.DrawBitmap(Bitmap,RectF(0,0,Bitmap.Width, Bitmap.Height),
RectF(0,0,Bitmap.Width, Bitmap.Height),1,True);
end;
end;
If i use timer paintbox is updateing for every image package
procedure TScreenViewFrm.Timer1Timer(Sender: TObject);
begin
pbScreenView.Repaint;
end;
I have to use Timer for repaint on my code but i dont want this and not working stable.
***Note: When i resize ScreenView form Paint box is updating. Why?
Do you have any idea?
Example Capture
https://gyazo.com/f880c2f172b0106122ea711389bf1659

After Client (I presume that is the packet receiver) has received a new image and it is stored in global Bitmap, do what you now do in the timer: pbScreenView.Repaint; (and remove the timer)

When drawing anything to a canvas in FMX you must use TCanvas.BeginScene and finish with TCanvas.EndScene, otherwise nothing will get drawn.
procedure TClient.DrawBitmap(Canvas: TCanvas);
begin
if assigned(Bitmap) then // Bitmap is global variable
begin
if Canvas.BeginScene then begin
try
Canvas.DrawBitmap(Bitmap,Bitmap.Bounds,Bitmap.Bounds,1,True);
finally
Canvas.EndScene;
end;
end;
end;
end;

Related

How can I stop changing style in firemonkey in ScaleChanged message

I use Firemokey 10.2. In macOS, internally when you move your from from a normal display to a retina display it automatically changes style of the controls. I would like to stop this message which is TScaleChangedMessage. I would appreciate If you could help me how can I stop this message in my app. In other word how can I stop changing from normal styles to High-Resolution Styles
The easiest way would be to create a copy of the FMX.Platform.Mac unit, and modify the TFMXWindow.windowDidChangeBackingProperties method so that the message is never sent, e.g:
procedure TFMXWindow.windowDidChangeBackingProperties(notification: NSNotification);
begin
// if (Application = nil) or (Application.Terminated) then
// Exit;
// try
// TMessageManager.DefaultManager.SendMessage(nil, TScaleChangedMessage.Create(Wnd), True);
// except
// HandleException(Self);
// end;
end;
i.e. just comment out everything in it
Unfortunately if you're using Delphi 10.2 Update 1, it means you'll need to include all the FMX units in the project path (so that they're also recompiled), due to this issue:
https://quality.embarcadero.com/browse/RSP-18836
I found the solution,
changing this function
function TMacWindowHandle.GetScale: Single;
begin
//Result := Wnd.backingScaleFactor
result := 1;
end;
will solve this problem :)

Not able to find the interactive gesture events like igiZoom, igiPan or igiRotate for vcl component in delphi XE7

I want to use the interactive gesture event for my windows application(for mouse and touch).
Although OnGesture(Sender: TObject; const EventInfo: TGestureEventInfo; var Handled: Boolean);
event is triggered, while zooming with two finger touch, I am always getting EventInfo.gestureId is 0. But I am getting the standard gestures.
Note : I am using Delphi XE7 for development and windows 8.1 touch device for testing.
procedure TForm1.GISGesture(Sender: TObject;
const EventInfo: TGestureEventInfo; var Handled: Boolean);
begin
if (EventInfo.GestureID = igipan) or(EventInfo.GestureID = igiZoom) then
begin
ShowMessage('zoom or pan');
end;
end;
Here EventInfo.GestureID is 0 whenever I tried to zoom with two finger or pan.
On VCL gestures like are igZoom and igRotate are disabled by default so no events are fired for them.
You can enable them through Touch property of your component that should react to these gestures.

Delphi 6 cursor not changing

If I have a ButtonClick event which sets Cursor := crHourglass, Application.ProcessMessages, then use a TOpenDialog to choose a file, and then do something CPU-intensive, the cursor behaves differently depending on whether it is over the existing control when the Open Dialog closes. If the cursor is over the control then the cursor remains as an hourglass; if it's outside the application completely and then moved into the area while the intensive process is still taking place, the cursor remains as an arrow. One cannot click or do anything so it's confusing to the user to get an arrow but not be able to do anything with it.
Stepping through the debugger shows the Cursor is -11 everywhere it should be. Using Screen.Cursor instead of Cursor has the same effect.
Is there a solution?
procedure TMyForm.LoadButtonClick(Sender: TObject);
begin
Cursor := crHourglass;
Application.ProcessMessages;
if OpenDialog.Execute then begin
// Do something intensive
// Cursor = crHourglass here but what is displayed is different
end;
Cursor := crDefault;
end;
First, make sure to set the cursor only while the CPU-intensive operation is active. Don't change the cursor while choosing a file — you never see any other programs do that, after all.
Second, when you say Cursor in your code, you're referring to the form's property. You might wish to use Screen.Cursor instead so that your entire program displays the same cursor.
Third, there's no need to call Application.ProcessMessages. Messages are going to be processed as soon as you display a dialog box anyway, and besides, there are no particular messages you need processed.
Finally, consider protecting the cursor changes with a try-finally block so that problems in your processing don't leave the cursor in the wrong state:
if OpenDialog.Execute then begin
Screen.Cursor := crHourglass;
try
// TODO: something intensive
finally
Screen.Cursor := crDefault;
end;
end;
If the operation really uses a lot of time, consider moving it off to another thread. Then you don't have to worry about the GUI being unresponsive, and so you won't have to change the cursor in the first place.

How can I get taskbar buttons for forms that aren't the main form?

How do you make a form appear on the taskbar in Delphi? In Firefox, for example, when you open a page in a new window, it creates another window on the taskbar without creating a new process. At the moment my Delphi application opens a new form when a button is clicked, but there is still only one thing on the task bar, so you can't alt-tab between the main form and the form that is created when the button is clicked. How do I change it so that the new form appears with a new taskbar button? My current code looks like this:
procedure Form1ButtonClick(Sender: TObject);
begin
Form2.Show;
end;
I have been messing around with CreateWindowEx, but ideally I would like to find a simpler solution than directly using the Windows API.
If I understand what you want correctly, you can show your secondary forms on the task bar by overriding it's CreateParams procedure, as explained in Minimize child forms independent of the main form delphi.about.com article, like this:
interface
type
TMyForm = class(TForm)
...
protected
procedure CreateParams(var Params: TCreateParams) ; override;
...
implementation
procedure TMyForm.CreateParams(var Params: TCreateParams) ;
begin
inherited;
Params.ExStyle := Params.ExStyle or WS_EX_APPWINDOW;
Params.WndParent := 0;
end;
if not using of this line is better in form order :
Params.WndParent := 0;

Showing a splash image is blank some seconds

In my application I have a splash image during connection to database and other initialization . It works fine to show the splash image, but there it is blank of a period.
So,
Splash image is loaded and shown a fraction of a second.
Splash image got blank 2-3 seconds.
Splash image is shown again some seconds.
Splash is closed.
Is there a clever thing to just show the image as quick as possible and remove the blank image ?
The code in the DPR-file:
Application.Initialize;
SplashForm := TSplashForm.Create(Application);
SplashForm.Show;
// Tried Splash.Update here but no difference.
SplashForm.SetPos(15);
// Init code
SplashForm.SetPos(30);
// More Init code
SplashForm.SetPos(100);
SplashForm.Close;
Application.Run;
And the splash unit:
procedure TSplashForm.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Action := caFree;
end;
procedure TSplashForm.FormCreate(Sender: TObject);
begin
pbLoading.Properties.Text := 'Loading ' + TClientConfig.Instance.AppTitle + '...';
end;
procedure TSplashForm.SetPos(aPos: Integer);
begin
pbLoading.Position := aPos;
UpDate;
end;
Regards
Roland
Your SplashForm needs to receive the WM_PAINT message in order to show itself, and that's not going to happen unless the message-pump is working.
Put Application.ProcessMessages after SplashForm.Show.
Perhaps it's not this obvious, but your code appears to show the splash screen and then immediately close it. What happens if you comment out the line that says SplashForm.Close?
I think I understand it now. My application use Bold and it takes some seconds to load the model. It is during that time the splash is blank. I managed to decrease that time a bit but I don't want to clutter the internals of Bolds SetFromModel with Application.ProcessMessages.
I think it is ok as this. But thanks for your comments. it points me in the right direction.
/Roland

Resources