2
My environment: C++ Builder XE4

I am working on hiding/showing one application from other application, both built using XE4.

Two project

  • UnitShow: to show/hide UnitHide
  • UnitHide: to be shown/hidden from UnitShow

The code for UnitShow is as follows:

void __fastcall TFormShow::B_showClick(TObject *Sender)
{
    HWND hwnd = GetDesktopWindow();
    hwnd = FindWindowEx(hwnd, NULL, L"TFormHide", NULL);

    ShowWindow(hwnd, SW_SHOWNORMAL);
}

The code for UnitHide is as follows:

void __fastcall TFormHide::B_hideClick(TObject *Sender)
{
    this->Hide();
}

With above, I tried followings.

  • On UnitHide, click B_hide >> UnitHide is hidden
  • On UnitShow, click B_show >> UnitHide is shown
  • On UnitHide, click B_hide >> UnitHide is not hidden

I expected that the 2nd B_hide button push will hide UnitHide.

What is the cause of this problem?

fantaghirocco
  • 4,761
  • 6
  • 38
  • 48
sevenOfNine
  • 1,509
  • 16
  • 37

2 Answers2

1

I tried followings.

void __fastcall TFormHide::B_hideClick(TObject *Sender)
{
    bool isShowing = this->Showing;
#if 1
    this->Hide();
#else
    ShowWindow(this->Handle, SW_HIDE);
#endif
}

When I use this->Hide(), after shown by UnitShow, the isShowing is false. With this, it seems this->Hide() does not work (after the 2nd time).

On the other hand, using ShowWindow(this->Handle, SW_HIDE); the isShowing is true always. With this, hiding after the 2nd time works.

For this->Hide(), it seems that I have to use this->Show() from other application, which currently I do not know how to do.

sevenOfNine
  • 1,509
  • 16
  • 37
0

Use FindWindow function instead of FindWindowEx as following:

procedure TfShow.btnShowClick(Sender: TObject);
var
  hWindow:Hwnd;
begin
  hWindow := FindWindow('TFormHide', nil);
  ShowWindow(hWindow, SW_SHOWNORMAL);
end;

Regarding the UnitHide you can call self.hide in your button

procedure TfHide.btnHideClick(Sender: TObject);
begin
  self.Hide; {Hide the hidden form }
  //or
  ShowWindow(Self.Handle, SW_HIDE);
end;

You can do the same calls in the C++

Update

as Remy mentions in his answer

So you can use the Following:

Define custom messages in the both applications

const
  Show_MESSAGE = WM_USER + 1;
  Hide_MESSAGE = Show_MESSAGE + 1;

In the HideUnit Define a handler for the message

  private
    { Private declarations }
    procedure WMShow(var Message: TMessage); message Show_MESSAGE;
    procedure WMHide(var Message: TMessage); message Hide_MESSAGE; 
....

implementation

procedure TfHide.WMShow(var Message: TMessage);
begin
  Self.Show;
end;

procedure TfHide.WMHide(var Message: TMessage);
begin
  Self.Hide;
end;

Sending the message form the ShowUnit > Showbtn

procedure TfShow.btnShowClick(Sender: TObject);
var
  hWndX : HWND;
begin
  hWndX := FindWindow('TfHide',nil);
  if hWndX <> 0 then begin
    SendMessage(hWndX, Show_MESSAGE, 0, 0);
  end
  else MessageBox(0, 'Window not found', 'Msg', 0);
end;

Hiding the Form from hidden form

procedure TfHide.btnHideClick(Sender: TObject);
begin
  SendMessage(Handle, Hide_MESSAGE, 0, 0);
end;
Community
  • 1
  • 1
RepeatUntil
  • 2,272
  • 4
  • 32
  • 57
  • This code behaves identically to that in the question unless I am mistaken. Am I? It's also written in the wrong language. Switching languages won't change the behaviour. – David Heffernan Apr 13 '16 at 06:40
  • @DavidHeffernan I'm not sure if its identical `FindWindow function instead of FindWindowEx` ..etc, All these API calls look the same in any languages. – RepeatUntil Apr 13 '16 at 07:04
  • So this is guesswork with no expectation that anything will change. The use of `ShowWindow` in the hide is different though. Why would you do that? Why does the `Hide` method fail? – David Heffernan Apr 13 '16 at 07:05
  • I tried using FindWindow instead of FindWindowEx(), with same results. And in C++ builder, `this->Hide()` corresponds to `self.Hide` in delphi. – sevenOfNine Apr 13 '16 at 07:12
  • Instead of using `this->Hide()`, I tried using `ShowWindow(this->Handle, SW_HIDE);`. This case, it worked. Thank you very much! – sevenOfNine Apr 13 '16 at 07:16
  • @seven Don't you want to understand? – David Heffernan Apr 13 '16 at 07:22
  • @DavidHeffernan Of course, I would like to understand the reason. Should I wait to mark as answer? – sevenOfNine Apr 13 '16 at 07:24
  • 1
    If it were me, I would supply a [mcve] in the question, and I would expect to get a complete explanation as to what is going on. In my view, the fact that `Hide` fails to hide the form is a sign that it has not been shown properly. I'd expect further trouble down the road. However, you accepted this answer and so blessed it. Which means you are unlikely to get anyone else digging in to gain understanding. I suspect that this method of programming by guesswork, trial and error, is a source of problems. – David Heffernan Apr 13 '16 at 07:30
  • @DavidHeffernan I agree. I am searching the reason. It seems that `this->Hide()` hides the Form, while `ShowWindow(hwnd, SW_SHOWNORMAL); shows the application. So this may cause imbalance of the hide/show behavior. – sevenOfNine Apr 13 '16 at 07:36
  • Why do you persist with the unsubstantiated recommendation of `FindWindow` over `FindWindowEx`? – David Heffernan Apr 13 '16 at 07:53
  • @RepeatUntil Thank you very much for the link and your example code. This is very helpful for me. – sevenOfNine Apr 13 '16 at 07:58
  • @DavidHeffernan What if the parent window of `TFormHide` not the desktop window ? – RepeatUntil Apr 13 '16 at 08:06
  • @RepeatUntil What if? `FindWindow` searches for top-level windows. – David Heffernan Apr 13 '16 at 08:15
  • 1
    @RepeatUntil Base on your delphi implementation, I implemented in C++ Builder for my future reference. http://qiita.com/7of9/items/89cabec42722704b4cbe – sevenOfNine Apr 14 '16 at 00:13