Thanks Jerome, Another question. Why I have to put an extra pointer (null) to call the NotifyModified() method? listBox1.NotifyModified(null, listBox, row) but not listBox1.NotifyModified(listBox, row) When I use the second, compiler says: not enough arguments for function listBox1.NotifyModified (2 given, expected 2) Isn't this funny?
Yes, you have a point that the error message is funny. The compiler errors need to be improved somewhat.
The Notify* methods are a special kind of method which I call "adaptive" methods which exist mainly to accommodate the "event notification" GUI system paradigm.
You can read about the details in the Tao (www.ecere.com/tao.pdf) at page 80-81.
- NotifyModified is meant to be called mainly from WITHIN the ListBox or derived classes - NotifyModified is meant to be overridden inside a form or dialog defining is as a child control; the form will act as the "MASTER" (or "owner")
The NotifyModified function pointer is located inside the ListBox's virtual functions table, which is why you can call it as "listBox1.NotifyModified" , but the type of the "this" object for the method IS NOT a ListBox, it is meant to be the MASTER of ListBox1 (which can be any class derived from Window). That is why an extra "this" pointer must be passed as an argument. It is expected to be called with listBox1's master so the proper call would be:
From inside the ListBox or derived class it is simply called as:
NotifyModified(master, this, row);
This notifies the owner of the ListBox that a row was modified, with a handle to itself (the ListBox).
However, you *probably* shouldn't be calling NotifyModified from outside. NotifyModified is automatically called when the contents of a row cell is modified. If you give a broader context (bigger sample code :) ) I might be able to guide you in how to best write it.
How can we have the system open a web page for us? I.e. we have a label "Programmed in ECERE IDE" on it and we want to tell the OS that it will open the web page "http://www.ecere.com" by the system-default browser. Also how can we send email to our address by one click on a label? At least it can again ask the OS for an email request?
So good. For now I am on windows but I will try all my code on Linux too some time. Cross-platform compatibility is one of my concerns when using this IDE.
There is not really a "ShellOpen" equivalent on Linux, so it just executes a system call for now.
I could add in functionality to detect a http or mailto command, but then I'd need to figure if there is a standard way of identifying the browser and mail client to launch it, and I don't believe there is any fully standard way of doing so. Let me know if you find one that would make sense and I will gladly add the support. You could also try your own way by adding code in OnLeftButtonDown with a #if defined(__WIN32__) and experiment with code to achieve what you want in Linux.
I believe Ecere is an excellent choice for cross-platform compatibility.
Try this ecere.dll for the moment in Windows for the SMTP code. Don't worry an up to date Linux version will be packaged in the next release.
Hi Jerome, What function echoes the chars in EditBox? Is there a function in EditBox class that we can overwrite to display * instead of the actual character as like the overwriting of paint() in Java? Thanks.
Hi ogozhan, yes you could override the "OnRedraw" method.
However the OnRedraw of the EditBox does a lot which is why I had decided to change the contents instead... But it might be a better idea to override OnRedraw and output it yourself.
No Jerome, that is not what I needed. Actually onRedraw handler is triggered so many times whenever even mouse passes over the control. Ok, what I try to do is, I have two editBoxes, lets say e1 and e2. in e1: OnKeyDown() { e2.notifyKeydown(...key...); } This way I hoped e2 would be updated with e1 but this does not work. Can I somehow send keystroke to another control?
Yes, there is OnActivate which is called on the control itself (With active = false when it lost the focus).
And there is NotifyActivate which is called on the control's master (But still overriden inside the control, in a similar way to a button's NotifyClicked.)
You can also check the "active" property of a control to know whether it is active, and you can check its parent's activeChild property to know if it is that parent's active control (That one will be set even if the parent itself is not active).
OnRedraw is triggered whenever the Ecere GUI system needs to draw the window (with surface.WriteText( )) If you write the display code in there it will work. I recommend you do this as it is the simplest way.
You can also send keystroke to another control by forwarding the OnKeyDown/OnKeyUp and/or OnKeyHit methods. But I don't think this is a good idea.
OnKeyHit did the job. Now I have a passwdBox, actually two editboxes. editBox1 is the one which I hit keys on it and displays *s. The other is the hidden editBox4 which is the clone of editBox1's actual values. In editBox1's definition: bool OnKeyHit(Key key, unichar ch) { form1.editBox4.OnKeyHit(key, ch); //this updates editBox4
return EditBox::OnKeyHit(key, '*'); //this updates editBox1 with *s }
The first approach to have a passwdBox with copying the last char of the contents to some other string did not work for me because I could not handle local (non-english) characters. Now I can handle the backspaces also.
Hmm, Almost-working solution. Home and End Keys are somehow sent by onKeyHit but also control keys are cathed by onKeyHit. It seems I will have to handle control keys like Shift or Ctrl. i.e. When I type capital G, It puts two *s in starBox but one char (G) in passBox. Also when I change the selection by mouse, everthing gets confused because the passBox is not aware of starBox'es selection changes. Reflecting mouse actions did not work. So I wonder if we have a handler that can handle and reflect selection changes (highligted characters and cursors position).
Jerome, Is there a general way to catch special keys like arrow keys, Ctrl, Shift, Function keys (f1, f2) and so on? When I examine the key argument I see only the last int sent by that key, I mean I can not see the 0 before 105 when left arrow key is hit.
The 0 before the 105? It doesn't work that way. You get one key hit for pressing one key. You can filter out the keys that you want to filter... You can use comparison operators and you can look at the Key class in the API reference for the values of each key. Combination keys have the key.alt, key.shift, key.ctrl flags set. You can also check if ch is non-zero to see if the key press gives you a character or not.
But really you should use the contents of your hidden edit box after you processed the key: count the number of characters in contents (using the UTF8 loop above so you handle international characters fine), and notice when you go pass the "charPos" property, that will be the number of asterisk after which you want to position the caret.
An input window? As in a form asking for information?
The easiest example is a message box. The Modal function will wait for an answer:
if(MessageBox { type = yesNo, contents = "Yes or no?" }.Modal() == yes) {
}
If you create your own form with its own contents, you can also hold on to the window so that you can then query the information from data members or controls:
MyForm form { }; incref form; // Keep a reference to it so we can read from it after it's destroyed if(form.Modal() == ok) // Let's assume the form has Ok / Cancel buttons (with id = DialogResult::ok/DialogResult::cancel, NotifyClicked = ButtonCloseDialog). { form.editBox1.contents; // Read the edit box here } delete form; // We're done with the form, take out our reference
It seem MessageBox has two members only; type and contents. That would be nice and more easy for me if it had or we could add an input field (EditBox) also.
How can I access the properties of a widget inside that widget? Is there a reserved word like "this" or "self"? In example I need to acess form1.button15.text inside button15 then I write code like: Button button15 { ... form1.button15.text ... }
If I write there this.text then it gives me the value of form1.access. If I write there self.text then it gives me nothing but an error :)
Then... Is there a generic object that represents the current widget?