Discussion:
strange behaviour of TForm
(too old to reply)
bar
2008-02-20 13:34:47 UTC
Permalink
Hi, all
In BCB 6.0, i created a AppBar.
Here is the complete code i have.

File->New Application
Save the Project As Project1 and Unit As Unit1.

Put a TButton on form.

Begin of Unit.h
==========
//---------------------------------------------------------------------------
#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published: // IDE-managed Components
TButton *Button1;
private: // User declarations
APPBARDATA abd;
void __fastcall WndProc(TMessage &Message);
void AppBarPosChanged(APPBARDATA);
void AppBarQuerySetPos(UINT uEdge, LPRECT lprc, PAPPBARDATA pabd);
public: // User declarations
__fastcall TForm1(TComponent* Owner);
__fastcall ~TForm1();
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif
End of Unit.h
==========

Begin of Unit1.Cpp
==============
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;

//User defined Callback message.
const int WM_ABNOTIFY=WM_USER+100;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
abd.cbSize = sizeof(abd);
abd.hWnd = Handle;
abd.uCallbackMessage = WM_ABNOTIFY;

// Register the AppBar by sending ABM_NEW message
SHAppBarMessage(ABM_NEW, &abd);

//At startup position the AppBar on Top
abd.uEdge = ABE_TOP;

abd.rc.left = Screen->WorkAreaLeft;
abd.rc.top = Screen->WorkAreaTop;
abd.rc.right = Screen->WorkAreaWidth;
abd.rc.bottom = abd.rc.top + 30;

SHAppBarMessage(ABM_QUERYPOS,&abd);
SHAppBarMessage(ABM_SETPOS,&abd);

Application->ProcessMessages();

SetWindowPos(abd.hWnd,HWND_TOPMOST, abd.rc.left, abd.rc.top,
abd.rc.right - abd.rc.left,abd.rc.bottom - abd.rc.top,
SWP_NOZORDER | SWP_NOACTIVATE);

MoveWindow(abd.hWnd, abd.rc.left, abd.rc.top,
abd.rc.right - abd.rc.left,
abd.rc.bottom - abd.rc.top, TRUE);
}
//---------------------------------------------------------------------------
__fastcall TForm1::~TForm1()
{
SHAppBarMessage(ABM_REMOVE, &abd);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::WndProc(TMessage &Message)
{
switch (Message.Msg)
{
case WM_ABNOTIFY:
switch (Message.WParam)
{
case ABN_WINDOWARRANGE:
break;
case ABN_STATECHANGE:
break;
case ABN_POSCHANGED:
AppBarPosChanged(abd);
break;
}
case WM_ACTIVATE:
SHAppBarMessage(ABM_ACTIVATE,&abd);
Message.Result=true;
break;
case WM_EXITSIZEMOVE:
SHAppBarMessage(ABM_QUERYPOS,&abd);
SHAppBarMessage(ABM_SETPOS,&abd);
Message.Result=true;
break;
case WM_WINDOWPOSCHANGED:
SHAppBarMessage(ABM_WINDOWPOSCHANGED,&abd);
Message.Result=true;
break;
default:
TForm::WndProc(Message);
}
}
//---------------------------------------------------------------------------
void TForm1::AppBarPosChanged(APPBARDATA pabd)
{
RECT rc;
RECT rcWindow;
int iHeight;
int iWidth;

rc.top = 0;
rc.left = 0;
rc.right = GetSystemMetrics(SM_CXSCREEN);
rc.bottom = GetSystemMetrics(SM_CYSCREEN);

GetWindowRect(pabd.hWnd, &rcWindow);

iHeight = rcWindow.bottom - rcWindow.top;
iWidth = rcWindow.right - rcWindow.left;

switch (pabd.uEdge)
{
case ABE_TOP:
rc.bottom = rc.top + iHeight;
break;

case ABE_BOTTOM:
rc.top = rc.bottom - iHeight;
break;

case ABE_LEFT:
rc.right = rc.left + iWidth;
break;

case ABE_RIGHT:
rc.left = rc.right - iWidth;
break;
}
AppBarQuerySetPos(pabd.uEdge, &rc, &pabd);
}
//---------------------------------------------------------------------------
void TForm1::AppBarQuerySetPos(UINT uEdge, LPRECT lprc, PAPPBARDATA pabd)
{
int iHeight = 0;
int iWidth = 0;

pabd->rc = *lprc;
pabd->uEdge = uEdge;

if ((uEdge == ABE_LEFT) || (uEdge == ABE_RIGHT))
{
iWidth = pabd->rc.right - pabd->rc.left;
pabd->rc.top = 0;
pabd->rc.bottom = GetSystemMetrics(SM_CYSCREEN);
}
else
{
iHeight = pabd->rc.bottom - pabd->rc.top;
pabd->rc.left = 0;
pabd->rc.right = GetSystemMetrics(SM_CXSCREEN);
}
Application->ProcessMessages();
SHAppBarMessage(ABM_QUERYPOS, pabd);
switch (uEdge)
{
case ABE_LEFT:
pabd->rc.right = pabd->rc.left + iWidth;
break;

case ABE_RIGHT:
pabd->rc.left = pabd->rc.right - iWidth;
break;

case ABE_TOP:
pabd->rc.bottom = pabd->rc.top + iHeight;
break;
case ABE_BOTTOM:
pabd->rc.top = pabd->rc.bottom - iHeight;
break;
}
Application->ProcessMessages();
SHAppBarMessage(ABM_SETPOS, pabd);
Application->ProcessMessages();

MoveWindow(pabd->hWnd, pabd->rc.left, pabd->rc.top,
pabd->rc.right - pabd->rc.left,
pabd->rc.bottom - pabd->rc.top, TRUE);
}
End of Unit1.Cpp
=============

Run the application, APPBAR form is creating.
Problem
1.When i changed the visible property of any components on the form, the
form is moving from its place

void __fastcall TForm1::FormClick(TObject *Sender)
{
Button1->Hide();
}
//---------------------------------------------------------------------------

I have tried other flags SWP_NOMOVE, SWP_NOSIZE of SetWindowPos() still the
same behaviour.
Is any wroung with the code.

Kind regards
SA
bar
2008-02-24 05:54:03 UTC
Permalink
Hi Experts,

Any suggestion please. What i am doing wroung.
I think i explained the problem. Please notify for any further info.

Regards
SA
Clayton Arends
2008-02-24 17:15:29 UTC
Permalink
Post by bar
Is any wroung with the code.
I have never worked with this type of code before so I don't know exactly
what the code should look like to accomplish its intended task. I noticed
two things which might not be intended:

1) In WndProc you seem to have left out a "break;"
Post by bar
switch (Message.Msg)
{
switch (Message.WParam)
{
break;
break;
AppBarPosChanged(abd);
break;
}
Notice there is no break for the WM_ABNOTIFY case. Which means the switch
will always roll into WM_ACTIVATE if a WM_ABNOTIFY message has been
received.

2) I'm pretty sure you should let TForm::WndProc execute for some of these
messages (maybe all of them) even if you handle the message. I modified
your code to do this and the resizing of the form didn't happen after I
clicked on the form. So the end of your WndProc to this:

// default:
// TForm::WndProc(Message);
}

TForm::WndProc(Message);
}

Change your code to what I show above until you decide which messages really
don't need to be handled by TForm as well.

Good luck,
Clayton
bar
2008-02-25 15:40:15 UTC
Permalink
2) I'm pretty sure you should let TForm::WndProc execute for some of these
Post by Clayton Arends
messages (maybe all of them) even if you handle the message. I modified
your code to do this and the resizing of the form didn't happen after I
// TForm::WndProc(Message);
}
TForm::WndProc(Message);
}
Change your code to what I show above until you decide which messages
really don't need to be handled by TForm as well.
Hi Mr.Clayton Arends

Your second suggestion solved the problem.
I have to allow the form to process the other messages.

Thank you very much for your time.

:) SA

Loading...