Developers' Area
| |
Not signed in (Sign In)

Vanilla 1.1.2 is a product of Lussumo. More Information: Documentation, Community Support.

    • CommentAuthorogozhan
    • CommentTimeMay 29th 2008
     
    Hi Jerome,
    I try to minimize my form when a command button on it is clicked. How can I do that?
    Thanks.
    •  
      CommentAuthorjerome
    • CommentTimeMay 29th 2008 edited
     
    Hi ogozhan, there are a few ways to do it. The easiest way is to set the "Window::state" property to "minimized", two other ways are commented:
    import "ecere"

    class Form1 : Window
    {
    text = "Form1";
    background = activeBorder;
    borderStyle = sizable;
    hasMaximize = true;
    hasMinimize = true;
    hasClose = true;
    size = { 640, 480 };

    Button button1
    {
    this, text = "button1", position = { 376, 192 };

    bool NotifyClicked(Button button, int x, int y,
    Modifiers mods)
    {
    state = minimized;
    //MenuWindowMinimize(null, 0);
    //SetState(minimized, false, 0);
    return true;
    }
    };
    }

    Form1 form1 {};
    • CommentAuthorogozhan
    • CommentTimeMay 31st 2008
     
    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?
    •  
      CommentAuthorjerome
    • CommentTimeMay 31st 2008 edited
     
    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:

    listBox1.NotifyModified(listBox1.master, listBox1, row);

    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.
    • CommentAuthorogozhan
    • CommentTimeJun 1st 2008
     
    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?
    •  
      CommentAuthorjerome
    • CommentTimeJun 1st 2008 edited
     
    This will work on Windows at least:
    class LinkLabel : Label
    {
    char * url;
    public property char * url
    {
    set { delete url; url = CopyString(value); }
    get { return url; }
    }
    ~LinkLabel() { delete url; }
    font = { "Arial", 10, bold = true, underline = true };
    foreground = blue;
    cursor = ((GuiApplication)__thisModule.application).
    GetCursor(hand);

    bool OnLeftButtonDown(int x, int y, Modifiers mods)
    {
    if(url) ShellOpen(url);
    return true;
    }
    };
    Then you can use it as:
    LinkLabel
    {
    this, position = { 150, 136 };
    text = "jerome@ecere.com";
    url = "mailto:jerome@ecere.com";
    };
    LinkLabel
    {
    this, position = { 150, 250 };
    text = "www.ecere.com";
    url = "http://www.ecere.com/";
    };
    Also take a look at smtp.ec for code to send an email.

    Just do import "smtp.ec" and then you can use it as:
    TempFile f { };
    f.Printf("This is a test email\n");
    SMTPSend("mailserver", "jerome@ecere.com",
    "ogozhan@somewhere.com", f);
    delete f;
    You might require an ecere.dll update for the Process method to be public, let me know if you're on Windows or Linux...
    • CommentAuthorogozhan
    • CommentTimeJun 1st 2008
     
    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.
    •  
      CommentAuthorjerome
    • CommentTimeJun 1st 2008 edited
     
    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.
    • CommentAuthorogozhan
    • CommentTimeJun 4th 2008
     
    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.
    •  
      CommentAuthorjerome
    • CommentTimeJun 4th 2008
     
    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.
    • CommentAuthorogozhan
    • CommentTimeJun 4th 2008
     
    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?
    • CommentAuthorogozhan
    • CommentTimeJun 4th 2008
     
    Can I detect if a control lost focus? Is there a handler triggered when a control is left (lost focus) i.e. selecting another control?
    •  
      CommentAuthorjerome
    • CommentTimeJun 4th 2008
     
    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).
    •  
      CommentAuthorjerome
    • CommentTimeJun 4th 2008
     
    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.
    • CommentAuthorogozhan
    • CommentTimeJun 4th 2008
     
    OK, to use OnKeyDown but how? My example does not work. What do I need to write inside OnKeyDown to pass the keystroke to another control?
    Thanks.
    •  
      CommentAuthorjerome
    • CommentTimeJun 4th 2008 edited
     
    void OnKeyDown(Key key, unichar ch, Modifiers mods)
    {
    control2.OnKeyDown(key, ch, mods);
    }
    void OnKeyHit(Key key, unichar ch, Modifiers mods)
    {
    control2.OnKeyHit(key, ch, mods);
    }
    void OnKeyUp(Key key, unichar ch, Modifiers mods)
    {
    control2.OnKeyUp(key, ch, mods);
    }
    Where control2 might have to be obtained by casting the master to the container as in:

    Window control2 = ((MyForm)master).myControl2;

    But it really is much easier to override OnRedraw, and it's not a performance problem if that's what you're worried about.
    • CommentAuthorogozhan
    • CommentTimeJun 4th 2008
     
    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.

    Thanks a lot.
    •  
      CommentAuthorjerome
    • CommentTimeJun 4th 2008
     
    I edited my post a few seconds later adding the Modifers which also need to be passed. You should add it to yours as well.

    Also, most operations are done in OnKeyHit, but some might be processed in OnKeyDown or OnKeyUp, such as the Home or End key maybe.

    I'm glad you got a working solution.

    The first approach might have been adapted by looping through the unicode characters with a function such as UTF8GetChar:
    int c, nb;
    for(c = 0; string[c]; c+= nb)
    {
    unichar ch = UTF8GetChar(string + c, &nb);
    }
    I think Ecere is very flexible and will sometimes allow you to achieve a goal in many different ways.
    • CommentAuthorogozhan
    • CommentTimeJun 4th 2008
     
    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).
    • CommentAuthorogozhan
    • CommentTimeJun 4th 2008
     
    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.
    •  
      CommentAuthorjerome
    • CommentTimeJun 4th 2008 edited
     
    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.
    • CommentAuthorogozhan
    • CommentTimeJun 8th 2008
     
    Hi,
    How can open an input window and wait for its return?
    Thanks.
    •  
      CommentAuthorjerome
    • CommentTimeJun 8th 2008
     
    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
    • CommentAuthorogozhan
    • CommentTimeJun 8th 2008
     
    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.
    •  
      CommentAuthorjerome
    • CommentTimeJun 8th 2008
     
    Unfortunately not, but you can make your own class which would work that way without too much difficulty...
    • CommentAuthorogozhan
    • CommentTimeJun 8th 2008 edited
     
    Can you send the source code of MessageBox?
    Thanks.
    •  
      CommentAuthorjerome
    • CommentTimeJun 8th 2008
     
    • CommentAuthorogozhan
    • CommentTimeNov 24th 2008
     
    Hi jerome,

    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?

    Thanks.
    •  
      CommentAuthorjerome
    • CommentTimeNov 24th 2008
     
    Hi oghozhan, there is no "self" keyword in eC, it is "this".

    Your button15 instance definition is inside a class definition, which is the "this" object. button15 is thus actually "this.button15".

    Simply button15.text should work.

    But usually, you do not require any member of the control you are initializing to initialize itself...
    • CommentAuthorogozhan
    • CommentTimeJan 31st 2010 edited
     
    .