Hi any idea how to add event to the constructed button in the run time?
I understand how to build component in the run time, but adding event is another thing. Got any example to explain how it works?
Thanks
A VCL event is just a pointer to a class method for a particular object. You can assign that pointer directly, eg:
__fastcall TForm1::TForm1(TComponent *Owner)
: TForm(Owner)
{
TButton *btn = new TButton(this);
btn->Parent = this;
// set other properties as needed...
btn->OnClick = &ButtonClicked;
/*
behind the scenes, this is actually doing the equivalent of this:
TMethod m;
m.Data = this; // the value of the method's hidden 'this' parameter
m.Code = &TForm1::ButtonClicked; // the address of the method itself
btn->OnClick = reinterpret_cast<TNotifyEvent&>(m);
*/
}
void __fastcall TForm1::ButtonClicked(TObject *Sender)
{
// do something ...
}
Related
To send data to multiple clients I create a TIdThreadSafeStringList in OnConnect and assign it to AContext->Data like so
AContext->Data = new TIdThreadSafeStringList
When the client disconnects, its stringlist is deleted in OnDisconnect like so
delete AContext->Data
However this results in an AV. If I zero the parameter, like so
delete AContext->Data
AContext->Data = NULL
the AV goes away. Is there some auto cleanup I'm not aware of?
Using C++ Builder 10.2.3.
Is there some auto cleanup I'm not aware of?
Yes. TIdContext derives from TIdTask, which owns the Data property. The TIdTask destructor is called after the OnDisconnect event and will free the Data object if it is not NULL.
Another (preferred) way to handle this situation is to instead derive a new class from TIdServerContext and add your TIdThreadSafeStringList to that class (and any other per-client custom functionality you want), eg:
class TMyContext : public TIdServerContext
{
public:
TIdThreadSafeStringList *MyList;
__fastcall TMyContext(TIdTCPConnection *AConnection, TIdYarn *AYarn, TIdContextThreadList *AList = NULL)
: TIdServerContext(AConnection, AYarn, AList)
{
MyList = new TIdThreadSafeStringList;
}
__fastcall ~TMyContext()
{
delete MyList;
}
//...
};
Then assign your class type to the server's ContextClass property at runtime before activating the server, eg:
__fastcall TMyForm::TMyForm(TComponent *Owner)
: TForm(Owner)
{
IdTCPServer1->ContextClass = __classid(TMyContext);
//...
}
Then, you can simply type-cast any TIdContext* pointer belonging to the server to your class type in order to access the TIdThreadSafeStringList (or other functionality):
static_cast<TMyContext*>(SomeIdContext)->MyList->...
This way, you can ignore the TIdContext::Data property altogether, or use it for other purposes, if desired.
I would like to declare a TBitmap Globally.
I tried as follows:
Locally within a method, this works fine
std::auto_ptr<Graphics::TBitmap> RenderGraphic(new Graphics::TBitmap());
OR
Graphics::TBitmap * RenderGraphic = new Graphics::TBitmap;
So to declare it globally I tried this in the header file
Graphics::TBitmap *RenderGraphic;
And this in the constructor
__fastcall TShipGraphic::TShipGraphic(TComponent* Owner)
: TForm(Owner)
{
Graphics::TBitmap * RenderGraphic = new Graphics::TBitmap;
}
Which compiles fine but when running, throws an access violation exception at the first occurrence of
RenderGraphic->Canvas->Pen->Color = clBlack;
Please advise, tks in advance.
The reference source I was using is C++ Builder Graphics Introduction
which suggested the declaration in the constructor
You need to implement a singleton. Consider read-only case (bitmap is created once, no setter function).
In MyGraphics.h define accessor function
#include <vcl.h>
TBitmap* GetRenderGraphic();
Implementation in MyGraphics.cpp
static std::unique_ptr<TBitmap> renderGraphic(new TBitmap());
TBitmap* GetRenderGraphic()
{
return renderGraphic.get();
}
Use it (required including of MyGraphics.h)
GetRenderGraphic()->Canvas->Pen->Color = clBlack;
I need help with something very interesting. I try to remove child from parent or fro stage dinamicly but not just removeChild and I want to destroy entire object. Here is very simple example what I want to do.
public function TestProject()
{
holder = new Sprite();
this.addChild(holder);
object1 = new Sprite();
object1.name = "object1";
object1.graphics.beginFill(0x6daeff);
object1.graphics.drawRect(0,0,100,100);
holder.addChild(object1);
stage.addEventListener(MouseEvent.CLICK,onClick);
}
protected function onClick(event:MouseEvent):void
{
var tmp:DisplayObject = holder.removeChild(object1);
tmp = null;
// holder.removeChild(object1) = null; this give me error.
}
//with this code object1 was removed from stage but object1 is not null. When I debug
object1 = flash.display.Sprite ; etc.
I want to remove child and at the same this child to be null.
Any ideas...
To clean up memory you have to destroy all references to your object. In this case:
protected function onClick(event:MouseEvent):void
{
if (holder.contains(object1))
holder.removeChild(object1);
object1 = null;
}
or
protected function onClick(event:MouseEvent):void
{
if (object1.parent)
object1.parent.removeChild(object1);
object1 = null;
}
Note: When you'd applied null to local variable tmp you didn't affect the object1 instance variable.
Thanks for your answer but the point is in this example I write just one object. I Ask when I have 100 object for example. Something like this:
for(var i:int=0;i<holder.numOfChilder;i++)
{
holder.getChildAt(i).addEventListener(Event.MouseEvent,onObjectClick)
}
function onObjectClick():void
{
holder.removeChild(event.currentTarget as DisplayObject) = null;
}
child object are dynamic created and I want dynamic removed
To cleanup object that was created dynamically and to which you have no reference variable, just remove all event listers to it, to make it eligible for GC:
function onObjectClick(event:MouseEvent):void
{
var target:DisplayObject = (event.currentTarget as DisplayObject);
target.removeEventListener(MouseEvent.CLICK, onObjectClick);
holder.removeChild(target);
}
Note: there is no need to set null to you local variable cause it will die automatically since method run will be finished
Note2: u can set useWeakReference=true during adding your listener
to allow your listener being garbage-collected automatically.
Have been seeing the term "Expando" used recently with Dart. Sounds interesting. The API did not provide much of a clue to me.
An example or two could be most helpful!
(Not sure if this is related, but I am most anxious for a way to add methods (getters) and/or variables to a class. Hoping this might be a key to solving this problem. (hint: I am using the Nosuchmethod method now and want to be able to return the value of the unfound method.))
Thanks in advance,
_swarmii
Just to clarify the difference between expando and maps: as reported in the groups, expando has weak references.
This means that a key can be garbage collected even if it's still present in the expando (as long as there are no other references to it).
For all other intents and purposes it's a map.
Expandos allow you to associate objects to other objects. One very useful example of this is an HTML DOM element, which cannot itself be sub-classed. Let's make a top-level expando to add some functionality to an element - in this case a Function signature given in the typedef statement:
typedef CustomFunction(int foo, String bar);
Expando<CustomFunction> domFunctionExpando = new Expando<CustomFunction>();
Now to use it:
main(){
// Assumes dart:html is imported
final myElement = new DivElement();
// Use the expando on our DOM element.
domFunctionExpando[myElement] = someFunc;
// Now that we've "attached" the function to our object,
// we can call it like so:
domFunctionExpando[myElement](42, 'expandos are cool');
}
void someFunc(int foo, String bar){
print('Hello. $foo $bar');
}
I played with it a little bit. Here's what I've got.
import 'dart:html';
const String cHidden = 'hidden';
class ExpandoElement {
static final Expando<ExpandoElement> expando =
new Expando<ExpandoElement>("ExpandoElement.expando");
final Element element;
const ExpandoElement._expand(this.element);
static Element expand(Element element) {
if (expando[element] == null)
expando[element] = new ExpandoElement._expand(element);
return element;
}
// bool get hidden => element.hidden; // commented out to test noSuchMethod()
void set hidden(bool hidden) {
if (element.hidden = hidden)
element.classes.add(cHidden);
else
element.classes.remove(cHidden);
}
noSuchMethod(InvocationMirror invocation) => invocation.invokeOn(element);
}
final Expando<ExpandoElement> x = ExpandoElement.expando;
Element xquery(String selector) => ExpandoElement.expand(query(selector));
final Element input = xquery('#input');
void main() {
input.classes.remove(cHidden);
assert(!input.classes.contains(cHidden));
input.hidden = true;
assert(x[input].hidden); // Dart Editor warning here, but it's still true
assert(!input.classes.contains(cHidden)); // no effect
input.hidden = false;
assert(!x[input].hidden); // same warning, but we'll get input.hidden via noSuchMethod()
assert(!input.classes.contains(cHidden));
x[input].hidden = true;
assert(input.hidden); // set by the setter of ExpandoElement.hidden
assert(input.classes.contains(cHidden)); // added by the setter
assert(x[input].hidden);
assert(x[input].classes.contains(cHidden)); // this is input.classes
x[input].hidden = false;
assert(!input.hidden); // set by the setter
assert(!input.classes.contains(cHidden)); // removed by the setter
assert(!x[input].hidden);
assert(!x[input].classes.contains(cHidden));
// confused?
assert(input is Element);
assert(x[input] is! Element); // is not
assert(x[input] is ExpandoElement);
assert(x is Expando<ExpandoElement>);
}
I have a TPageControl with a number of TTabSheets that contain TForms (or possibly TFrames, but TForms for now).
When a tab comes into view I would like the TForm or TFrame to be notified it has come to the front. I can't find anything that does that.
I know I can get the Active TTabSheet in the OnChange event, so I tried to add this class to the TForm:
struct iTab
{
virtual void DoIt( void ) = 0;
};
with the this in the OnChange:
ICPTab *tab = dynamic_cast<ICPTab *>( sheet->Controls[ 0 ] );
Thinking I could use RTTI to get the iTab pointer and call DoIt() from the
And I get the warning:
[BCC32 Warning] Unit1.h(18): W8130 Interface 'IPTab' does not derive from IUnknown. (Interfaces should derive from IUnknown)
[BCC32 Warning] MainWindow.cpp(612): W8131 Casting Delphi style class 'TControl' to an interface. Use 'System::interface_cast<ICPTab>(cls)' instead
I am not interested in getting all of IUnknown just so that the form can use an interface.
I can get the TFrame or TForm pointer using:
TForm *tab = dynamic_cast<TForm *>( sheet->Controls[ 0 ] );
but can't call a non TForm method with this pointer. Would it be ok to call the Activate() method?
So how do I notify the TForm or TFrame that it is now showing?
You have to derive iTab from IUnknown (or IInterface) or order to use it as an interface correctly. The compiler warning even hints that you can use interface_cast to extract an interface from a Delphi-style (aka TObject-derived) object. Alternatively use TObject::GetInterface() instead.
Otherwise, if you just want to call methods of your custom TForm class, then just type-cast the child control pointer from your TTabSheet to your actual TForm-derived class:
TMyForm *tab = dynamic_cast<TMyForm *>( sheet->Controls[ 0 ] );
if( tab != NULL ) tab->DoSomething();
Or:
static_cast<TMyForm *>( sheet->Controls[ 0 ] )->DoSomething();
I went with the following code:
void __fastcall TgMainWindow::mPageControlChange( TObject* Sender )
{
NOT_USED( Sender );
TTabSheet* sheet = mPageControl->ActivePage;
if ( sheet->ControlCount > 0 )
{
// form or frame, we will attempt to call the OnActivate method
TForm* form = dynamic_cast<TForm *>( sheet->Controls[ 0 ] );
if ( form == NULL )
{
ShowMessageDlg( this, L"Programming Error: Initial child on tabsheet must be a TForm", mtError, TMsgDlgButtons( ) << mbOK );
}
else
{
if ( form->OnActivate != NULL )
{
form->OnActivate( this );
}
else
{
ShowMessageDlg( this, L"Programming Error: From must have an OnActivate event", mtError, TMsgDlgButtons( ) << mbOK );
}
}
}
}
Since a form on a tabsheet never has its OnActivate method called, this works quite well.
note: the method sample is not complete, there is no call to OnDeactivate