C++ Builder bizarre issue (taskbar icon not appearing)? - forms

I have an application with a login form (which is the main form) and a main form, which is opened after the log-in one is filled in with the correct info.
However, the program icon does not appear on the taskbar. I would like to ask, why does this happen?

I don't think there is anything bizarre in this behaviour.
I assume You hide login form after user provides login information?
By default Main form owns taskbar:
Application->MainFormOnTaskBar = true;
So either make frmMain "main" instead of LoginForm and create login form dynamically before main Form (this will make login form invisible on taskbar) or add following code to frmMain -
in header:
void __fastcall CreateParams(Controls::TCreateParams &Params);
and in the .cpp file:
void __fastcall frmMain::CreateParams(Controls::TCreateParams &Params)
{
TForm::CreateParams(Params);
Params.ExStyle = Params.ExStyle | WS_EX_APPWINDOW;
Params.WndParent = ParentWindow;
}
WS_EX_APPWINDOW "Forces a top-level window onto the taskbar when the window is visible."
As described in this MSDN article
and Embarcadero DocWiki.

Related

In Delphi, how to restore a minimized modal form that is not the main form

In the project source, I detect a previous instance of my app, and open it then terminate the new instance.
Remember, I do this in the project source.
The application has a main form that can open a second modal form. If the second, modal, form is not open when the app is minimized (or the user switches to another application) it works fine.
The old main form is opened and the new instance is terminated. However, if the second modal form is minimized, its parent main form is also minimized. That's good UI behavior.
The problem exists when attempting to restore the modal form by a new instance. I can't seem to get the modal form to restore.
I can restore the main form, however the modal form still has focus, but is hidden.
This prevents any user action on the now visible main form. From the user's point of view, the app is hung.
The modal form's caption does not change, so it's easy to get its handle.
The app has a DataModule, which is created first. I do all the duplicate app testing in the project source after the DM is created, but before any other forms are, and well before Application.Run.
That assures that the handles I acquire come from the existing app.
I've tried:
PreviousHandle := FindWindow(nil, PAnsiChar('Form Editor'))
ShowWindow(PreviousHandle,SW_RESTORE);
ShowWindow(PreviousHandle,SW_NORMAL);
BringWindowToTop(PreviousHandle);
The best I've gotten out of variations of this is restoring the main form.
When the handle is for the modal form, it sometimes shows in the lower left as a minimized form.
I say sometimes because I've tried so many variations of the above that I don't remember exactly how this code sample behaved.
All I know is, whatever I've tried from the project source did not restore the modal form, so I tried sending a custom Windows Message to the modal form.
I know the message arrived and the message handler caught it. Example:
if not PostMessage(PreviousHandle,WM_RESTORE_FORM,PreviousHandle,0) then
ShowMessage('Can''t automatically show the Form program. '+
'Please click the taskbar icon.');
Here's what the message handler looks like. It is in the Modal Form. As you can see, I pass the form's handle as a Message param. I've verified that it arrives.
Here's the code in a TApplicationEvents OnMessage event:
procedure TfrmDisplayForm.ApplicationEvents1Message(var Msg: tagMSG;
var Handled: Boolean);
var
oldHwnd : THandle;
begin
if Msg.message = WM_RESTORE_ACORD then
begin
oldHwnd := Msg.lParam;
if ForceForegroundWindow(OldHwnd) then ShowMessage('true') else ShowMessage('False');
Handled := True;
end;
end;
Here's the function that is called. However, I've tried various ShowWindows(...) combinations with no luck. Actually, this function didn't do the trick either.
function TfrmDisplayForm.ForceForegroundWindow(hWnd: THandle): BOOL;
var
hCurWnd: THandle;
begin
{credit Peter Below}
hCurWnd := GetForegroundWindow;
AttachThreadInput(GetWindowThreadProcessId(hCurWnd, nil),
GetCurrentThreadId, True);
Result := SetForegroundWindow(hWnd);
AttachThreadInput(GetWindowThreadProcessId(hCurWnd, nil),
GetCurrentThreadId, False);
end;
I've been working on this for a couple of days, and don't know what I'm doing wrong.
Question: How can I restore the modal form? It must be possible because it restores perfectly when the taskbar icon is clicked.
Don't try to restore individual forms instead use TApplication.Restore
Calling TApplication.Restore will restore all of the application windows to the state before the whole application was minimized same as clicking on TaskBar icon of the application.
PS: I also hope you are not allowing users to minimize individual Modal forms. Or you may also run into a problem where application seems to be stuck.

Multiple delphi forms

I have two delphi forms; frmHome and frmStats. There is a button on the main form (frmHome) and when you click on it it takes you to frmStats.
On btn click in frmHome:
frmStats.ShowModal;
Hide;
This works fine but on frmStats there is also a button that I would like to take the user back to the main form when clicked on. The problem is I get error messages.
If I make reference to the form like this I get the error message "cannot make visable window modal"
implementation
uses frmHome_u;
However if I make reference like this, then i get the message "circular unit reference"
interface
uses {a bunch of uses} , frmHome_u;
On btn click in frmStats:
frmHome.ShowModal;
Hide;
How do I do this?
Modal forms have owners. These owning forms are disabled when the modal form is shown. A form is always shown above its owner.
You are trying to make form1 be the owner of form2 and then in turn have form2 own form1. That circular ownership is not allowed. It would imply that both windows would be disabled, and each window on top of the other.
What you need to do is to close the modal form. Replace
frmHome.ShowModal;
Hide;
with
ModalResult := mrOK;
If you want both forms to be visible and enabled at the same time, then you must not show them modally.
If I understand what you are trying to do then this should work just fine.
frmStats.Enabled := True;
frmStats.Show;
Enabled := False;
Hide;
And you have the reciprocal code in the other form.
Because the other form is disabled, it can not be brought into focus until you enable it.
EDIT
If the users closes FrmStats and FrmHome is the mainform then you must enable it in the onclose event.

Detect if there is a modal form showing

Is there some method of detecting if there is a modal form showing in my VB6 application.
I want to show another form modally if there is a modal form showing and modeless if there isn't a modal form showing.
I know I can do some error handling to detect this and show modally if the error occurs:
Public Sub ShowFormModeless(frm As Form, Optional ownerForm As Form = Nothing)
On Error GoTo ShowModal
Call frm.Show(, ownerForm)
Exit Sub
ShowModal:
Call frm.Show(vbModal, ownerForm)
End Sub
But I want to be able to detect this without the error being thrown.
Try checking App.NonModalAllowed. Note that this property does not detect modal forms being shown from other (than current module) projects, i.e. if your application consists of main executable and several ActiveX dlls each of these projects will have a separate App object and Forms collection.
The result is that if a dll is showing a modal form only its own project's App.NonModalAllowed is flagged. So once again, App.NonModalAllowed is not a process-wide flag but a per project one.
Note that this flag tracks VB6 only forms, so if you are using API dialogs (open/save file, color picker, etc) this does not enter VB6 runtime's modal loop, so nothing is flagged.
If you application is a single exe then using this flag works as expected.

Open Eclipse Welcome Page To Page Other Than "home-page-id"

I have a properly functioning Eclipse RCP program which opens the org.eclipse.ui.intro extension to a home-page-id of root.xhtml. Inside of the root.xhtml home page, there are links to other XHTML pages to offer help.
I am trying to create buttons throuhout my GUI which, when you click them, they would take you to the correct XHTML documentation page. All I can figure out so far is how to get the buttons to take me to the root.xhtml page, but I cannot figure out how to tell the intro page to navigate to a different page. Here is the code I am using now to open the intro page:
help_button.addSelectionListener(new SelectionAdapter()
{
public void widgetSelected(SelectionEvent event)
{
ActionFactory.INTRO.create(DataStore.getInstance().getCurrentWorkbenchPage().getWorkbenchWindow()).run();
}
})
For example, I am trying to do something like this where the hyperlink string in quotes is exactly the same as the hyperlink in the root.xhtml file:
ActionFactory.INTRO.create(DataStore.getInstance().getCurrentWorkbenchPage().getWorkbenchWindow()).run().navigateTo("http://org.eclipse.ui.intro/showPage?id=setuplogging");
I was able to figure this out, it was rather time consuming and painful to do so - hopefully it helps someone out. At least the answer is a few lines of code.
You have to show the intro site getIntroSite() first before changing the URL otherwise you will get a null pointer exception in IntroURL. If you get the null pointer exception when calling createIntroURL(), it may have to do with an intro site not being already open in your GUI, not necessarily that your link is bad. Also, if the intro is already open, don't try to reopen it because it will change the page to the home page rather than your page identified with page_id. So, for this class, I made the help button a toggle button meaning if the intro window is open, then the button is pressed. In some cases I close the intro site if it is already open when the button is pressed (example below), in other cases I just don't update the intro site so it won't go to the home page (example not shown, but just omit the first part of the if block).
If you try the ActionFactory run() code in my question, that will display the intro site in the entire Window. I wanted the intro site to be a sub-window within the perspective, so I used the method below by setting showIntro(null, true) - true meaning don't take up the entire window (they call the Boolean standby).
The page_id corresponds to the page id setup in your documentation XML file when setting up your extension point org.eclipse.ui.intro.config content variable.
final IIntroPart
intro = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().
getWorkbenchWindow().getWorkbench().getIntroManager().
getIntro();
if (PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().
getWorkbenchWindow().getWorkbench().getIntroManager().
isIntroStandby(intro))
{
PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().
getWorkbenchWindow().getWorkbench().getIntroManager().
closeIntro(intro);
help_button.setSelection(false);
}
else
{
PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().
getWorkbenchWindow().getWorkbench().getIntroManager().
showIntro(null, true).getIntroSite();
IIntroURL
introURL = IntroURLFactory.createIntroURL(
"http://org.eclipse.ui.intro/showPage?id=" + page_id);
introURL.execute();
help_button.setSelection(true);
}

How to create a "New xxx" popup?

I have a Grid object and added a [ (+) New Client ] button which I'd like to open a popup form to create the new client with a couple fields.
I've looked at the code examples in the website but haven't found how to do it (sorry if I've missed something).
This is the current page code:
function page_clients_listing($p){
$g = $p->add('Grid');
$g->addColumn('text','first_name');
$g->addColumn('text','last_name');
$g->addColumn('inline','telephone');
$g->addColumn('expander','comments');
$g->setSource('client');
$g->addButton('With Icon')->set('Add New Client')->setIcon('Plus');
}
Thanks in advance!
You can either create a popup or a dialog. Dialog is based on jQuery UI dialog implementation. Popups are likely to be blocked and are harder to control.
This is actually working for any object (you can apply to view, button, image, icon, etc), but I'll use button).
$b=$g->addButton('Add New Client')->setIcon('Plus');
$b->js('click')->univ()->frameURL($title,$url);
// OR
$b->js('click')->univ()->dialogURL($title,$url);
$url would most likely be returned by api->getDestinationURL(). The other page would be loaded and scripts on that page will be evaluated. Let's say you are on other page and now need to close the window.
$result = $this->addButton('Close')->js('click')->univ()->closeDialog();
closeDialog() returns a jQuery chain object pointing to a view which originally opened the frame. As a result if you do $result->hide(); then after dialog is closed, the original button ('add new client') will also be hidden.
Here is example to show some additional things you can do with frames, reloading and custom event handlers:
http://agiletoolkit.org/example/refresh1