How to create a Sidebar form in delphi - delphi

How can I create a Sidebar form in delphi.
I try the ScreenSnap and Align properties but I need that the form stay visible even if the user maximize other forms, without been on top. Just like the windows sidebar do.
Update: From the comments: if a window is maximized, it maximizes next to the window, not in front of or behind.

What you're looking for is called an AppBar. Begin your research with the ShAppBarMessage API function.

You can call a Windows API function to force your application to stay on top:
SetWindowPos(Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);

Related

Delphi: how to show trayicon balloon without showing taskbar when set to autohide

How can I avoid the taskbar popping up when set to autohide, when using ShowBalloonHint?
The notification area in Windows has a defined behavior. You can wish it behaved differently, but that doesn't change the fact that what you want to do cannot be done.
Sorry for the inconvience.
A close workaround would be to create a TOOLTIP window yourself, and position it on the screen near where you think the user's notification area might be:
bottom right
top right
bottom left
primary monitor
secondary monitor
That will involve using
GetSystemMetrics(SM_CXFULLSCREEN)
GetSystemMetrics(SM_CYFULLSCREEN)
SystemParametersInfo(SPI_GETWORKAREA)
Then you create a TOOLTIPS_CLASS window:
FHandle := CreateWindow(TOOLTIPS_CLASS, PChar(''),
WS_POPUP or TTS_BALLOON,
Integer(CW_USEDEFAULT), Integer(CW_USEDEFAULT),
Integer(CW_USEDEFAULT), Integer(CW_USEDEFAULT),
0, 0, HInstance,
nil);
Then you would send it the TTM_SETTITLE, TTM_UPDATETIPTEXT, TTM_TRACKPOSITION messages, and finally the big moment: TTM_TRACKACTIVATE:
And then sometime later you hide the tooltip with another call to TTM_TRACKACTIVATE.
You're free to follow Windows user experience guidelines, or you can roll your own.

Bring modeless form with WindowState=wsNormal behind MdiChild?

Is it possible to show a modeless "wsNormal" WindowsState form behind a MDIChild form? I want to create a NOTE form which is always behind other forms (but always in front of the MDI form), unless you bring it to the front. E.g when you click on it.
That's technically impossible for window that is not an child of the MDI container.
The MDI children are child windows of the MDI container which is a child of the main form. If a window is in front of the main form, then it is in front of the MDI children. If it is behind the main form, then it is behind the MDI children.
Normally no, MDI parent is the root parent of MDI childs, you're either below the MDI parent or above. But you can set the parent of your top-level form to be the MDICLIENT.
I wouldn't suggest this approach as it possibly would have complications (maybe(?) you can achieve the same effect by tweaking some other MDI client class). But if you want to try what it would look like create a new "MDI Application" project and change the code that runs from the Help->About menu item to:
procedure TMainForm.HelpAbout1Execute(Sender: TObject);
begin
// AboutBox.ShowModal;
windows.SetParent(AboutBox.Handle, ClientHandle);
AboutBox.Show;
SetWindowPos(AboutBox.Handle, HWND_BOTTOM, 0, 0, 0, 0,
SWP_NOSIZE or SWP_NOMOVE);
end;

Inserting set of controls at runtime is extremely slow

We have a point-of-sale application and in this application we have a scrollbox container. If the seller selects a product, then a new product row is created and inserted into the scrollbox. The product row component is a frame - textboxes, buttons and labels in it.
But here's a little problem by inserting this product row control into the scrollbox at runtime. It's slow. I can see how selecting product draws edittext components slowly into the scrollbox.
I tried to set the components' visibility to false before ScrollBox.InsertControl and enabling it after, but it doesn't help speed up things very much. Also I read about DisableAlign/EnableAlign thing, but I don't know exactly where I have to put this line of code.
How can I speed up inserting this custom component into the form's scrollbox container?
TScrollBox doesn't have BeginUpdate/EndUpdate, but you can get the same effect using WM_SETREDRAW messages. I would probably avoid more heavy handed methods like LockWindowUpdate.
SendMessage(ScrollBox1.Handle, WM_SETREDRAW, 0, 0);
try
// add controls to scrollbox
// set scrollbox height
finally
SendMessage(ScrollBox1.Handle, WM_SETREDRAW, 1, 0);
RedrawWindow(ScrollBox1.Handle, nil, 0, RDW_ERASE or RDW_INVALIDATE or RDW_FRAME or RDW_ALLCHILDREN);
end;
Normally, a control adding to a container takes very little time. There's a high probability this has something to do with the creation of the control rather the insertion.
Try disabling screen updates when adding controls and enable screen update when done in a try-finally routine. Then the screen doesn't have to update for each separate control but just once, when all controls are placed.

Delphi - Create form behind another form

I'm using Delphi 4.
I have a main form with a button that dynamically creates a new form.
I'd like the new form to be visible, but to show up BEHIND the main form.
I've tried calling SendToBack() immediately after FormCreate(). But that makes the window flicker quickly before it's actually sent to back.
I've tried making the form invisible, then SendToBack(), then Visible := true.
But the new form is still at the front.
It looks like SendToBack() only works with visible forms? How can I cause the form to be shown behind the main form?
This worked for me:
SetWindowPos(newform.Handle, HWND_BOTTOM, 0, 0, 0, 0, SWP_SHOWWINDOW
or SWP_NOMOVE or SWP_NOOWNERZORDER or SWP_NOSIZE or SWP_NOACTIVATE);
newform.Visible := true;
Thanks for help!
make the second window (e.g. form2) invisible, then call:
showWindow(form2.handle,SW_SHOWNOACTIVATE);
-don

Delphi: Show window without activation

I struggle to show a second form above the main form without losing focus.
I have tried ShowWindow(second.handle, SW_SHOWNOACTIVATE), but the mainform loses focus.
If I set Visible := false on the second window, the call to ShowWindow does not activate the second form, but the windows is empty when shown...
Does anyone have a good recipe for this?
UPDATE: What I'm trying to do, is showing a notify-window at a given event. It's crucial that the main form does not lose focus at any time.
There has to be something wrong with your code.
I tested this code, it works:
procedure TForm1.Button1Click(Sender: TObject);
begin
ShowWindow(Form2.Handle, SW_SHOWNOACTIVATE);
Form2.Visible := True;
end;
Be careful to use Visible, not Show ! Otherwise it'll override the SW_SHOWNOACTIVATE.
You can show the window (non modal) and reset the focus to the mainwindow.
procedure TMainForm.ButtonClick(Sender: TObject);
begin
OtherForm.Show;
SetFocus;
end;
Tested on 2006.
This does not show the other form on top. But it is very counter intuitive to have a window on top that does not have the focus.
I've used this in the past
SetWindowPos(WindowHandle, HWND_TOP, 0, 0, 0, 0, SWP_NOACTIVATE or SWP_NOSIZE or SWP_NOMOVE);
I've not tested this with recent versions of Delphi though...
If possible, you should considered using some sort of tool tip window to display the notification information. A tool tip will not steal focus from you main window when it is displayed or when a user clicks on it. A regular form will have a border by default and if the user clicks on that border your main form will loose focus.
Here is some basic code to do this. The tip disappears when free is called; however you would be better off setting a timer than using sleep.
with THintWindow.Create(nil) do
try
ActivateHint(MyRect, 'My Notification');
Sleep(DisplayTime);
finally
Free;
end
Here you are:
// you have set your 2nd form as non resizable, without border nor title etc...
Form2.Enabled := False; // prevent the 2nd form to grab focus even when clicked
SetWindowPos(Form2.Handle, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW or SWP_NOACTIVATE or SWP_NOSIZE or SWP_NOMOVE);
// be sure to hide it automatically when done as it is disabled...
I did this in the past, but I don't have the code because it was propietary in last job (sorry).
If I remember well, what I did was:
From client class A call a procedure (or function) that doesn't belongs to any class (a traditional Pascal method).
From that method, call some method in a class B that doesn't inherit from TForm
From the method in B, create an instance of popup form P, but with no parent or owner; and call a method in the instance.
From the method called in the instance, show itself.
The code (of step 3) could go something like this:
var p: TPopupForm;
begin
p := TPopupForm.Create(nil);
p.ShowWindow;
p.Release;
end;
I'm sorry if this doesn't work, I don't have Delphi too.
Daniels code works until ...
ShowWindow(Form2.Handle, SW_SHOWNOACTIVATE);
Form2.Visible := True;
Until your second form is created dynamically. Then your second form is located at position 0,0 with default width and height.
For a short moment when ShowWindow is executed you will see the second form on screen, disappearing when the next line is executed.
I am using the code for a transparent overlay form which is created dyamically. The following code is a combination of the given answers and places the second form without activation over the parent form.
SetWindowPos(Form2.Handle, HWND_TOP, Left, Top, Width, Height, SWP_NOACTIVATE);
Form2.Visible := True;

Resources