Board index » cppbuilder » Re: Popup Bubble Messages

Re: Popup Bubble Messages


2004-11-10 04:12:22 PM
cppbuilder88
"Lynn Morrison" < XXXX@XXXXX.COM >wrote in message
<snip>
Quote
class TMainForm: public TForm
{
TMyHintWindow *MHintWindow;

};

//---------main.cpp

__fastcall TMainForm::TMainForm(TComponent* Owner)
: TForm(Owner)
{
MHintWindow = new TMyHintWindow(Owner);
::HintWindowClass = (TMetaClass*)MHintWindow;
}

The error I'm getting is,

[Linker Error] Unresolved external '__fastcall
Controls::THintWindow::NCPaint(void *)' referenced from
D:\BDEV\BRFTP\UNIT2.OBJ

<snip>
Check out the Help on HintWindowClass in BCB - you don't need to instantiate
it, just assign the class ID of your THintWindow-derived replacement to the
global variable. For example:
HintWindowClass = __classid(TMyHintWindow);
The VCL them instantiates TMyHintWindow instead of THintWindow when it needs
a hint window.
BTW, I'd also consider calling inherited::CreateParams(Params) in
TMyHintWindow::CreateParams.
HTH,
GT.
 
 

Re:Re: Popup Bubble Messages

Quote
Check out the Help on HintWindowClass in BCB - you don't need to
instantiate
it, just assign the class ID of your THintWindow-derived replacement to
the
global variable. For example:

HintWindowClass = __classid(TMyHintWindow);

The VCL them instantiates TMyHintWindow instead of THintWindow when it
needs
a hint window.

BTW, I'd also consider calling inherited::CreateParams(Params) in
TMyHintWindow::CreateParams.

Ok, I tried both those things and I am still getting the same error in
the linking. This class resides in a seperate .cpp file and is included by
my MainForm's cpp file only.
Thanks for the info. Can you tell me if I am doing something wrong? Here is
what I have done...
#ifndef MyHintH
#define MyHintH
#include <vcl.h>
//--------------------------------------------------------------------------
-
class TMyHintWindow : public THintWindow
{
public:
__fastcall TMyHintWindow(Classes::TComponent *Owner):THintWindow(Owner) {}
__fastcall ~TMyHintWindow() {}
void __fastcall CreateParams(TCreateParams &Params);
};
#endif
//------------ .cpp
#include "MyHint.h"
//--------------------------------------------------------------------------
-
void __fastcall TMyHintWindow::CreateParams(TCreateParams &Params) {
inherited::CreateParams(Params);
Params.Style = WS_POPUP | TTS_NOPREFIX | TTS_BALLOON | WS_VISIBLE;
}
#pragma package(smart_init)
//---------- main.cpp
constructor
HintWindowClass = __classid(TMyHintWindow);
Lynn
 

Re:Re: Popup Bubble Messages

"Lynn Morrison" < XXXX@XXXXX.COM >wrote in message
Quote
Ok, I tried both those things and I am still getting the same error in
the linking. This class resides in a seperate .cpp file and is included by
my MainForm's cpp file only.
I think your linker problem might be resolved by constructing
TMyHintWindow's header like a 'regular' BCB unit header, something like:
//--------------------------------------------------------------------------
-
#ifndef MyHintWindowH
#define MyHintWindowH
//--------------------------------------------------------------------------
-
#include <SysUtils.hpp>
#include <Controls.hpp>
#include <Classes.hpp>
#include <Forms.hpp>
//--------------------------------------------------------------------------
-
class TMyHintWindow : public THintWindow
{
typedef THintWindow inherited;
public:
__fastcall TMyHintWindow(Classes::TComponent *Owner):THintWindow(Owner)
{}
etc. etc. (BTW - the typedef for inherited is really going to help you, and
CreateParams should really be protected, I think.)
Then, <vcl.h>should be included at the top of your CPP file, something like
this:
//--------------------------------------------------------------------------
-
#include <vcl.h>
#pragma hdrstop
//--------------------------------------------------------------------------
-
#include "MyHintWindow.h"
//--------------------------------------------------------------------------
-
#pragma package(smart_init)
void __fastcall TMyHintWindow::CreateParams(TCreateParams &Params)
{
inherited::CreateParams(Params);
etc. etc.
Quote
Thanks for the info. Can you tell me if I am doing something wrong? Here
is
what I have done...
In addition to what you've done with CreateParams, I think you'll need more
code to get the balloon tips going. A quick experiment with your code shows
that you've done enough to replace the hint window class, but I think you'll
just get a borderless regular-style hint.
I don't know what else you'll need to do, I'm afraid ... the only
THintWindow work I've done was a version that implemented its own
ActivateHintData, CalcHintRect, IsHintMsg and Paint methods. No different
style.
 

{smallsort}

Re:Re: Popup Bubble Messages

Quote
I think your linker problem might be resolved by constructing
TMyHintWindow's header like a 'regular' BCB unit header, something like:

Some more info here...
After looking at controls.pas, I see that NCPaint is declared as
procedure THintWindow.NCPaint(DC: HDC);
Now I am not sure what an HDC is, but the compiled header for controls.pas
says NCPaint(void*)...
If this were true, and just in case, I made an override for NCPaint using
void* and although the compiler was happy, the linker was not and I got the
same error. Then I tried using HDC and it would't compile at all.
I'm stumped... it all looks as it should, but alas, only standard looking
hints.
Lynn
 

Re:Re: Popup Bubble Messages

"Lynn Morrison" < XXXX@XXXXX.COM >wrote in message
Quote
Then I tried using HDC and it would't compile at all.

I'm stumped... it all looks as it should, but alas, only standard looking
hints.
Lynn,
Are you using BCB5? If so, try sending me the project source (zipped!) and
I'll see if there's anything obvious ... you should be able to work out my
email from the post header,
GT.
 

Re:Re: Popup Bubble Messages

"Graham Thompson" < XXXX@XXXXX.COM >wrote in
message news:419221ba$ XXXX@XXXXX.COM ...
Quote
Are you using BCB5? If so, try sending me the project source (zipped!) and
I'll see if there's anything obvious ... you should be able to work out my
email from the post header,

No, I am using BCB 6 Pro(SP4)
Lynn
 

Re:Re: Popup Bubble Messages

"Lynn Morrison" < XXXX@XXXXX.COM >wrote in message
Quote
No, I am using BCB 6 Pro(SP4)
OK, I've posted a bare-bones BCB5 framework project that should give you a
form with TMyHintWindow. TMyHintWindow doesn't do anything different from
THintWindow, but it should give you a place to start.
Hopefully BCB6 can 'convert' the project from BCB5, or you can add the
source to a new BCB6 project.
The project doesn't specify any packages, so hopefully that should make it
easier to convert.
The post is in borland.public.attachments, with the Subject "Hint project
framework for Lynn".
Good luck!
GT.
 

Re:Re: Popup Bubble Messages

Quote
OK, I've posted a bare-bones BCB5 framework project that should give you a
form with TMyHintWindow. TMyHintWindow doesn't do anything different from
THintWindow, but it should give you a place to start.

Hopefully BCB6 can 'convert' the project from BCB5, or you can add the
source to a new BCB6 project.
<I replied in that group as well, but in case you did not see it>
It still does not link. I had to change your Windows::TRect to Types::TRect.
Perhaps that type was moved since BCB 5 to BCB 6. No biggy
Ok, now this boggles the mind. I have done some research into the VCL
source on this and all I can say is HOW did anyone ever derive from
THintWindow without any problems under BCB 6? It cannot work without certain
overrides. Problem here is the HIDESBASE useage, or at least I think so...
(read on)
My linker error states that it is looking for NCPaint(void *), yet in the
automatically generated header for controls.pas, there is no such function
signature, only TMessage and HDC. HDC looks like it could be a printer DC or
NULL.... I assume from this that void * and NULL are synonymous ,which must
be the case or it wouldn't have compiled.
BUT.... (and again, not knowing for sure) it also uses HIDESBASE. In the
help for hidesbase it says...
//--------------------
The compilers use the HIDESBASE macro, defined in sysmac.h, to specify that
these types of function declarations are completely separate. For example,
if a base class T1 declares a virtual function, func, taking no arguments,
and its derived class T2 declared a function with the same name and
signature, DCC32 -jphn would produce an HPP file with the following
prototype:
virtual void T1::func(void);
HIDESBASE void T2::func(void);
Without the HIDESBASE declaration, the C++ program semantics indicate that
virtual function T1::func() is being overridden by T2::func().
//---------------------
This last line is what got to me. In this case, don't we WANT T1::func()
to be overridden by T2::func()? It seems to me that by hiding its base and
it also being virtual, that you HAVE to implement it in your code? If you
did not, then this linker error would indeed surface, as it does not find
the object code because I did not provide the override. If I declare an
NCPaint func in my own inherited class, it will indeed link ok, but I still
do not see anything. This part I will figure out myself.... the point being
is that I get the impression that it could simply have been a pure virtual
function without all this redirection. At least a noob to the vcl such as I
am would not have to go on a witch hunt to find out the inner workings, I
could merely have seen it as a pure virt and overriden it as appropriate....
further on this... The code is indeed there, IOW the .pas file does have an
implementation for this function, yet it does not link.... I just don't get
it at all.
I should put in a report to QC regarding this....
Comments are welcome
Lynn
 

Re:Re: Popup Bubble Messages

Yes, that is how it is declared, I snipped it for brevity...
Quote
I think your linker problem might be resolved by constructing
TMyHintWindow's header like a 'regular' BCB unit header, something like:


Lynn
 

Re:Re: Popup Bubble Messages

"Lynn Morrison" < XXXX@XXXXX.COM >wrote in message
Quote
Ok, I did this like you suggested...
Not quite. You did not call the inherited CreateParams() to initialize the
window, you only set the attributes but did not make the other API calls
needed to work with balloon hints, and you did not assign the
HintWindowClass correctly at all.
Try this instead (untested):
class TMyHintWindow : public THintWindow
{
protected:
virtual void __fastcall CreateParams(TCreateParams &Params);
public:
__fastcall TMyHintWindow(TComponent *Owner) : THintWindow(Owner) {}
virtual void __fastcall ActivateHint(TRect Rect, const AnsiString
AHint);
};
void __fastcall TMyHintWindow::CreateParams(TCreateParams & Params)
{
THintWindow::CreateParams(Params);
CreateSubClass(Params, TOOLTIPS_CLASS);
Params.Style = WS_POPUP | TTS_NOPREFIX | TTS_BALLOON;
}
void __fastcall TMyHintWindow::ActivateHint(TRect Rect, const AnsiString
AHint)
{
TOOLINFO ti = {sizeof(TOOLINFO), 0};
ti.uFlags = TTF_TRANSPARENT | TTF_CENTERTIP;
ti.hwnd = Handle;
ti.lpszText = AHint.c_str();
// fill in other members of the TOOLINFO with the
// coordinates of the component that is displaying the
// hint window.
//
// Here is the tricky part - the VCL does not expose access
// to the HintControl that is displaying the hint, except from the
// TApplication::OnShowHint event, so you probably have to
// store that HintControl pointer globally so that your hint window
// can then access it when needed, since the hint window is not
// instantiated until after the OnShowHint event returns.
SendMessage(Handle, TTM_ADDTOOL, 0, (LPARAM) &ti );
THintWindow::ActivateHint(Rect, AHint);
}
__fastcall TMainForm::TMainForm(TComponent* Owner)
: TForm(Owner)
{
::HintWindowClass = __classid(TMyHintWindow);
}
Gambit
 

Re:Re: Popup Bubble Messages

Quote
Try this instead (untested):
<snip>
Ok, I tried that, but I am still getting the linker error(using BCB 6
Pro(SP4)). Here is the error
[Linker Error] Unresolved external '__fastcall
Controls::THintWindow::NCPaint(void *)' referenced from
D:\BDEV\TEST\MAIN.OBJ
[C++ Warning] MyHint.h(30): W8022 '_fastcall
TMyHintWindow::ActivateHint(TRect,const AnsiString)' hides virtual function
'_fastcall THintWindow::ActivateHint(const TRect &,const AnsiString)'
Here is the code I cut from your example(I left the destructor there, I saw
no harm in it),
//MyHint.h
#ifndef MyHintH
#define MyHintH
#include <SysUtils.hpp>
#include <Controls.hpp>
#include <Classes.hpp>
#include <Forms.hpp>
//--------------------------------------------------------------------------
-
class TMyHintWindow : public THintWindow
{
typedef THintWindow inherited;
public:
__fastcall TMyHintWindow(Classes::TComponent *Owner):THintWindow(Owner) {}
__fastcall ~TMyHintWindow() {}
virtual void __fastcall ActivateHint(TRect Rect, const AnsiString AHint);
protected:
virtual void __fastcall CreateParams(TCreateParams &Params);
};
#endif
// MyHint.cpp
#include <vcl.h>
#pragma hdrstop
#include "MyHint.h"
#pragma package(smart_init)
//--------------------------------------------------------------------------
-
void __fastcall TMyHintWindow::CreateParams(TCreateParams &Params) {
THintWindow::CreateParams(Params);
CreateSubClass(Params, TOOLTIPS_CLASS);
Params.Style = WS_POPUP | TTS_NOPREFIX | TTS_BALLOON;
}
void __fastcall TMyHintWindow::ActivateHint(TRect Rect, const AnsiString
AHint)
{
TOOLINFO ti = {sizeof(TOOLINFO), 0};
ti.uFlags = TTF_TRANSPARENT | TTF_CENTERTIP;
ti.hwnd = Handle;
ti.lpszText = AHint.c_str();
// fill in other members of the TOOLINFO with the
// coordinates of the component that is displaying the
// hint window.
//
// Here is the tricky part - the VCL does not expose access
// to the HintControl that is displaying the hint, except from the
// TApplication::OnShowHint event, so you probably have to
// store that HintControl pointer globally so that your hint window
// can then access it when needed, since the hint window is not
// instantiated until after the OnShowHint event returns.
SendMessage(Handle, TTM_ADDTOOL, 0, (LPARAM) &ti );
THintWindow::ActivateHint(Rect, AHint);
}
// Main.cpp constructor
::HintWindowClass = __classid(TMyHintWindow);
 

Re:Re: Popup Bubble Messages

"Remy Lebeau (TeamB)" < XXXX@XXXXX.COM >wrote in message
Quote
Try this instead (untested):
<snip>
Remy: Thanks for your help ... CreateSubClass, never knew about that one!
All: I've implemented Remy's (untested) code in BCB5 under XP, and just get
an empty, rectangular Hint. Anyone got any ideas?
Thanks muchly,
GT.
 

Re:Re: Popup Bubble Messages

On Fri, 12 Nov 2004 09:16:01 -0000, Graham Thompson wrote:
Quote
"Remy Lebeau (TeamB)" < XXXX@XXXXX.COM >wrote in message
news:4193bd73$ XXXX@XXXXX.COM ...
>Try this instead (untested):
<snip>

Remy: Thanks for your help ... CreateSubClass, never knew about that one!

All: I've implemented Remy's (untested) code in BCB5 under XP, and just get
an empty, rectangular Hint. Anyone got any ideas?

Thanks muchly,

GT.
Graham,
Been looking through previous postings, and trying a few things, as I have
had the same results as you. Haven't had time to try this yet, but when I
was looking through a solution which worked in VB (sorry!!) I noticed there
was a xxx.exe.manifest file (where xxx is the project name).
Don't know if this will work, but it's worth a try as the manifest
references Microsoft.Common.Controls.
If you have any success, please let me know.
--
Darrel Couzens
InnSource Solutions Inc
www.innsourcesolutions.com