Watch, Follow, &
Connect with Us

For forums, blogs and more please visit our
Developer Tools Community.


Welcome, Guest
Guest Settings
Help

Thread: I'd like the MainForm to be the (only) one to show up under Alt-Tab


This question is not answered. Helpful answers available: 2. Correct answers available: 1.


Permlink Replies: 10 - Last Post: Oct 1, 2017 4:34 PM Last Post By: Scott Pinkham Threads: [ Previous | Next ]
Free Dorfman

Posts: 139
Registered: 2/4/12
I'd like the MainForm to be the (only) one to show up under Alt-Tab  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Sep 25, 2017 11:05 PM
Seattle | FMX

I have a multi-device app that has a secondary window (for "debugging" / testing purposes) that I send text to (under Windows only).

Everything is fine here (almost!) and I have been using this approach" for years and years. 20+ under Windows programming and 2+ under FMX. However (this is the "almost!" part) under FMX sometimes this is the window that appears in <Alt-Tab>.

I create this form
 jFmxBugForm := TjFmxBugForm.Create(Application); 
within initialization code.

At any rate, it was that anytime this window was open IT would be the window showing up under <Alt-Tab>. I got somewhat better results by setting its BorderStyle to SizeToolWin. Now, if it is the form with focus, <Alt-Tab> show the MainForm (as desired). However, if the MainForm has focus, <Alt-Tab> shows this "bug message" window.

Any thoughts?

Thanks!
Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: I'd like the MainForm to be the (only) one to show up under Alt-Tab [Edit]  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Sep 26, 2017 9:44 AM   in response to: Free Dorfman in response to: Free Dorfman
Free Dorfman wrote:

Everything is fine here (almost!) and I have been using this
approach" for years and years. 20+ under Windows programming and 2+
under FMX. However (this is the "almost!" part) under FMX sometimes
this is the window that appears in <Alt-Tab>.

Only top-level unowned windows with the WS_EX_APPWINDOW style appear on
the Taskbar or Alt-Tab window. Unfortunately, FMX does not allow you
to customize the attributes used for window creation, like VCL does.
However, it is possible to gain access to the underlying Win32 HWND
after it is created (see FMX.Platform.Win.FormToHWND() and related
functions), so you can use the Win32 API SetWindowLong/Ex() function to
change its styles, at least. For instance, to replace WS_EX_APPWINDOW
with WS_EX_TOOLWINDOW.

At any rate, it was that anytime this window was open IT would be the
window showing up under <Alt-Tab>. I got somewhat better results by
setting its BorderStyle to SizeToolWin.

That is an easier way to do it.

Now, if it is the form with focus, <Alt-Tab> show the MainForm (as
desired). However, if the MainForm has focus, <Alt-Tab> shows this
"bug message" window.

It shouldn't be. That is not how the Alt-Tab window works.

--
Remy Lebeau (TeamB)
Free Dorfman

Posts: 139
Registered: 2/4/12
Re: I'd like the MainForm to be the (only) one to show up under Alt-Tab [Edit]  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Sep 26, 2017 3:08 PM   in response to: Remy Lebeau (Te... in response to: Remy Lebeau (Te...
I appreciate the help. But I still can't figure it out.

I am trying:

procedure TjFmxBugForm.FormCreate(Sender: TObject);
{$IFDEF MSWINDOWS}
var
  Wnd: Winapi.Windows.HWND;
begin
Wnd := FormToHWND(Self);
 
//first I tried this:
//
//SetWindowLong(Wnd,GWL_EXSTYLE,GetWindowLong(Wnd,GWL_EXSTYLE) or WS_EX_TOOLWINDOW);
 
//then - mostly guessing - if I'm being honest, I tried this:
//
SetWindowLong(Wnd,0,WS_EX_TOOLWINDOW);
 
{$ELSE}
begin
{$ENDIF}
end;


Neither of these is changing the behavior at all (whether this form's BorderStyle is Sizeable or SizeToolWin).

I realize I probably just didn't (fully) understand your original reply. Still, I am stuck...
Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: I'd like the MainForm to be the (only) one to show up under Alt-Tab [Edit] [Edit]  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Sep 26, 2017 4:00 PM   in response to: Free Dorfman in response to: Free Dorfman
Free Dorfman wrote:

I am trying:

Don't do it in the Form's OnCreate event. Override the Form's virtual
CreateHandle() method instead.

And don't just apply WS_EX_TOOLWINDOW without also removing
WS_EX_APPWINDOW as well.

procedure TjFmxBugForm.CreateHandle;
{$IFDEF MSWINDOWS}
var
  Wnd: Winapi.Windows.HWND;
  Style: LONG_PTR;
{$ENDIF}
begin
  inherited;
  {$IFDEF MSWINDOWS}
  Wnd := FormToHWND(Self);
  Style := GetWindowLongPtr(Wnd, GWL_EXSTYLE);
  SetWindowLongPtr(Wnd, GWL_EXSTYLE, (Style and not WS_EX_APPWINDOW) or
WS_EX_TOOLWINDOW);
  {$ENDIF}
end;


But, like I said, setting BorderStyle to ToolWindow or
SizeToolWin would already take care of this for you.

--
Remy Lebeau (TeamB)
Free Dorfman

Posts: 139
Registered: 2/4/12
Re: I'd like the MainForm to be the (only) one to show up under Alt-Tab [Edit] [Edit]  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Sep 26, 2017 6:40 PM   in response to: Remy Lebeau (Te... in response to: Remy Lebeau (Te...
Remy,

Unless I've introduced some other issue, changing the "PopupForm" BorderStyle (to either SizeToolWin or ToolWindow) does NOT fix the problem.

It half fixes it.

Now (with it set to SizeToolWin or ToolWindow) when I <Alt-Tab> while the PopupForm is active, I see the MainForm. However, if the MainForm is active, and I <Alt-Tab> I am seeing PopupForm.

I just thought of this... the PopupForm may be created first.

Looked into that. It WAS being created first. Changed that. Now it isn't created until after MainForm is fully up (and I click a button).

No difference. I'm off to try your CreateHandle approach. Back in a few...
Free Dorfman

Posts: 139
Registered: 2/4/12
Re: I'd like the MainForm to be the (only) one to show up under Alt-Tab [Edit] [Edit]  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Sep 26, 2017 6:57 PM   in response to: Free Dorfman in response to: Free Dorfman
Still farked. (Pardon my Battlestar Galactica)

Added:
//interface
  TjFmxBugForm = class(TjForm)
    {$IFDEF MSWINDOWS}
    protected
      procedure CreateHandle; override;
    {$ENDIF}
 
//implementation
{$IFDEF MSWINDOWS}
procedure TjFmxBugForm.CreateHandle;
var
  Wnd: Winapi.Windows.HWND;
  Style: LONG_PTR;
begin
inherited;
Wnd := FormToHWND(Self);
Style := GetWindowLongPtr(Wnd,GWL_EXSTYLE);
SetWindowLongPtr(Wnd,GWL_EXSTYLE,(Style and not WS_EX_APPWINDOW) or WS_EX_TOOLWINDOW);
end;
{$ENDIF}

So. Now. MainForm Created and Shown. I click a button, PopupForm Created and Shown. From this point on, if I <Alt-Tab> while the MainForm is active - under Windows 10.1, I should probably add - no matter what Windows program is active, when I <Alt-Tab> I see the PopupForm. With text over it matching the title bar text from the MainForm. That "from the MainForm" part is interesting...?

I'm still stuck and not sure what else to do. And so appreciative of your time and effort here. :`)

P.S. And I am "walking it through" the CreateHandle call with the debugger.

P.P.S. I changed
  TjFmxBugForm = class(TjForm)

to
  TjFmxBugForm = class(TForm) ////TjForm

no difference

P.P.P.S. I changed
  jFmxBugForm_ := TjFmxBugForm.Create(Application);

to
  jFmxBugForm_ := TjFmxBugForm.Create(nil);

no difference

Apologies. I should gather more thoughts. And THEN post.

Sorry. Adding this tidbit as well:
object jFmxBugForm: TjFmxBugForm
  Left = 0
  Top = 0
  BorderStyle = SizeToolWin
  Caption = '[%s]'
  ClientHeight = 480
  ClientWidth = 640
  FormFactor.Width = 320
  FormFactor.Height = 480
  FormFactor.Devices = [Desktop]
  OnCreate = FormCreate
  OnKeyDown = FormKeyDown
  OnResize = FormResize
  OnShow = FormShow
  DesignerMasterStyle = 0
end

Absolutely nothing noteworthy in any of FormCreate, FormShow, FormResize, FormKeyDown.
Scott Pinkham

Posts: 54
Registered: 3/19/07
Re: I'd like the MainForm to be the (only) one to show up under Alt-Tab [Edit] [Edit]  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Sep 26, 2017 7:19 PM   in response to: Free Dorfman in response to: Free Dorfman
I'm not sure if this makes any difference, but instead of (Style and not WS_EX_APPWINDOW) or WS_EX_APPWINDOW, I'd do ((Style xor WS_EX_APPWINDOW) or WS_EX_APPWINDOW) to clear the bit.

Also, not to be pedantic, but it should be "fraked" not "farked" :-)

-Scott

Free Dorfman wrote:
Still farked. (Pardon my Battlestar Galactica)

Added:
//interface
  TjFmxBugForm = class(TjForm)
    {$IFDEF MSWINDOWS}
    protected
      procedure CreateHandle; override;
    {$ENDIF}
 
//implementation
{$IFDEF MSWINDOWS}
procedure TjFmxBugForm.CreateHandle;
var
  Wnd: Winapi.Windows.HWND;
  Style: LONG_PTR;
begin
inherited;
Wnd := FormToHWND(Self);
Style := GetWindowLongPtr(Wnd,GWL_EXSTYLE);
SetWindowLongPtr(Wnd,GWL_EXSTYLE,(Style and not WS_EX_APPWINDOW) or WS_EX_TOOLWINDOW);
end;
{$ENDIF}

So. Now. MainForm Created and Shown. I click a button, PopupForm Created and Shown. From this point on, if I <Alt-Tab> while the MainForm is active - under Windows 10.1, I should probably add - no matter what Windows program is active, when I <Alt-Tab> I see the PopupFomr. With text over it that's the title bar text from the MainForm. That "from the MainForm" part is interesting...

I'm still stuck and not sure what else to do. And so appreciative of your time and effort here. :`)

P.S. And I am "walking it through" the CreateHandle call with the debugger.

P.P.S. I changed
  TjFmxBugForm = class(TjForm)

to
  TjFmxBugForm = class(TForm) ////TjForm

no difference

P.P.P.S. I changed
  jFmxBugForm_ := TjFmxBugForm.Create(Application);

to
  jFmxBugForm_ := TjFmxBugForm.Create(nil);

no difference

Apologies. I should gather more thoughts. And THEN post.

Sorry. Adding this tidbit as well:
object jFmxBugForm: TjFmxBugForm
  Left = 0
  Top = 0
  BorderStyle = SizeToolWin
  Caption = '[%s]'
  ClientHeight = 480
  ClientWidth = 640
  FormFactor.Width = 320
  FormFactor.Height = 480
  FormFactor.Devices = [Desktop]
  OnCreate = FormCreate
  OnKeyDown = FormKeyDown
  OnResize = FormResize
  OnShow = FormShow
  DesignerMasterStyle = 0
end

Absolutely nothing noteworthy in any of FormCreate, FormShow, FormResize, FormKeyDown.
Free Dorfman

Posts: 139
Registered: 2/4/12
Re: I'd like the MainForm to be the (only) one to show up under Alt-Tab [Edit] [Edit]  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Sep 26, 2017 8:29 PM   in response to: Scott Pinkham in response to: Scott Pinkham
Reworked the routine slightly. No logic change.
procedure TjFmxBugForm.CreateHandle;
var
  Wnd: Winapi.Windows.HWND;
  OldStyle, NewStyle: LONG_PTR;
begin
inherited;
Wnd := FormToHWND(Self);
OldStyle := GetWindowLongPtr(Wnd,GWL_EXSTYLE);
NewStyle := (OldStyle and not WS_EX_APPWINDOW) or WS_EX_TOOLWINDOW;
SetWindowLongPtr(Wnd,GWL_EXSTYLE,NewStyle);
end;

Then I tried each of these:
NewStyle := (((OldStyle xor WS_EX_APPWINDOW) or WS_EX_APPWINDOW)) or WS_EX_TOOLWINDOW;
 
NewStyle := ((OldStyle xor WS_EX_APPWINDOW) or WS_EX_APPWINDOW);


Now... most interesting of all. TWO entries in the <Alt-Tab> Gallery.
If the PopupForm is active, I see both windows. Correctly. Each with its own TitleBarText above it.
If the MainForm is active, I see PopupForm twice. One with its TitleBarText and one with that of MainForm.

Again, whether my program is the active one or not, under Win10.1 | FMX | Seattle
Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: I'd like the MainForm to be the (only) one to show up under Alt-Tab [Edit] [Edit]  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Sep 27, 2017 10:35 AM   in response to: Free Dorfman in response to: Free Dorfman
Free Dorfman wrote:

NewStyle := (((OldStyle xor WS_EX_APPWINDOW) or WS_EX_APPWINDOW)) or
WS_EX_TOOLWINDOW;

NewStyle := ((OldStyle xor WS_EX_APPWINDOW) or WS_EX_APPWINDOW);
{code}

Those are forcing WS_EX_APPWINDOW to be ON, which the whole point of
this discussion was to turn it OFF instead. And you can't mix
WS_EX_APPWINDOW with WS_EX_TOOLWINDOW.

--
Remy Lebeau (TeamB)
Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: I'd like the MainForm to be the (only) one to show up under Alt-Tab [Edit] [Edit]  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Sep 27, 2017 10:33 AM   in response to: Scott Pinkham in response to: Scott Pinkham
Scott Pinkham wrote:

I'm not sure if this makes any difference, but instead of (Style and
not WS_EX_APPWINDOW) or WS_EX_APPWINDOW, I'd do ((Style xor
WS_EX_APPWINDOW) or WS_EX_APPWINDOW) to clear the bit.

Won't that turn ON the style if it is not already ON? Using (AND NOT),
the style will always be turned OFF whether it is ON or OFF.

--
Remy Lebeau (TeamB)
Scott Pinkham

Posts: 54
Registered: 3/19/07
Re: I'd like the MainForm to be the (only) one to show up under Alt-Tab [Edit] [Edit]  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Oct 1, 2017 4:34 PM   in response to: Remy Lebeau (Te... in response to: Remy Lebeau (Te...
Oops, you are right (as usual). Wouldn't it be nice if you could use Delphi's set operators for this? That would make it very plain what the intentions are, something like this:

Exclude(Style, WS_EX_APPWINDOW)

I frequently switch back and forth between C (mostly for embedded microprocessors) and Delphi, and set operators are what I miss most when using C.

-scott

Remy Lebeau (TeamB) wrote:
Scott Pinkham wrote:

I'm not sure if this makes any difference, but instead of (Style and
not WS_EX_APPWINDOW) or WS_EX_APPWINDOW, I'd do ((Style xor
WS_EX_APPWINDOW) or WS_EX_APPWINDOW) to clear the bit.

Won't that turn ON the style if it is not already ON? Using (AND NOT),
the style will always be turned OFF whether it is ON or OFF.

--
Remy Lebeau (TeamB)
Legend
Helpful Answer (5 pts)
Correct Answer (10 pts)

Server Response from: ETNAJIVE02