|
|
Home » Community » Newbie corner » Focus problem
Focus problem [message #57784] |
Tue, 14 December 2021 21:23  |
Silvan
Messages: 56 Registered: December 2014 Location: Trento (IT)
|
Member |
|
|
Problem description:
in the simple test app below I can't unfocus the editstring ctrl so when I use the keyboard to move
the character on the string the key pressed goes also on the edit control.
I suppose it is silly but I can't find a simple solution and I don't understand the focus and
event mechanism.
Greetings
Thank you
Silvan
#include <CtrlLib/CtrlLib.h>
using namespace Upp;
struct MainWindow : TopWindow {
Point p;
EditString inputtext;
virtual void Paint(Draw& w)override
{
int x,y;
w.DrawRect(GetSize(), SWhite());
w.DrawText(p.x, p.y, "#", Arial(30), Red);
}
void Close() override
{
delete this;
}
virtual bool Key(dword key, int count) override
{
switch (key)
{
case K_W:
p.y-=1;
break;
case K_S:
p.y+=1;
break;
case K_A:
p.x-=1;
break;
case K_D:
p.x+=1;
break;
default:
//C Statements
;
}
Refresh();
return true;
}
// Costruttore dove inserisci le inizializzazioni
MainWindow()
{
Title("Test Focus").Zoomable().Sizeable();
Add(inputtext.TopPosZ(0, 16).HSizePos());
inputtext <<= "test";
SetRect(0, 0, 300, 300);
p.x = 150;
p.y = 150;
}
};
GUI_APP_MAIN
{
(new MainWindow)->OpenMain();
Ctrl::EventLoop();
}
|
|
|
|
|
Re: Focus problem [message #57799 is a reply to message #57798] |
Sat, 18 December 2021 05:39   |
Lance
Messages: 656 Registered: March 2007
|
Contributor |
|
|
Hi Silvan:
I manage to create the following example.
THISBACK is legacy code. Event<>, Gate, etc now are alias of Function.
In IDE, Ctrl+Left Click on the Event type name will bring you to its definition, you should see something like this
template <typename... ArgTypes>
using Event = Function<void (ArgTypes...)>;
template <typename... ArgTypes>
using Gate = Function<bool (ArgTypes...)>;
template <class Ptr, class Class, class Res, class... ArgTypes>
Function<Res (ArgTypes...)> MemFn(Ptr object, Res (Class::*method)(ArgTypes...))
{
return [=](ArgTypes... args) { return (object->*method)(args...); };
}
BTW, revised code to do what you asked and demonstrate a callback.
#include <CtrlLib/CtrlLib.h>
using namespace Upp;
struct MainWindow : TopWindow {
Point p;
EditString inputtext;
virtual void Paint(Draw& w)override
{
int x,y;
w.DrawRect(GetSize(), SWhite());
w.DrawText(p.x, p.y, "#", Arial(30), Red);
}
void LeftDown(Point p, dword keyflags)override
{
SetFocus();
}
// void Close()override
// {
// // delete this;
// }
bool Key(dword key, int count) override
{
switch (key)
{
case K_W:
p.y-=1;
break;
case K_S:
p.y+=1;
break;
case K_A:
p.x-=1;
break;
case K_D:
p.x+=1;
break;
case K_UP:
case K_DOWN:
case K_LEFT:
case K_RIGHT:
WhenSuspiciousKey();
}
Refresh();
return true;
}
// Costruttore dove inserisci le inizializzazioni
MainWindow()
{
Title("Test Focus").Zoomable().Sizeable().WantFocus();
Add(inputtext.TopPosZ(0, 16).HSizePos());
inputtext <<= "test";
SetRect(0, 0, 300, 300);
p.x = 150;
p.y = 150;
}
Event<> WhenSuspiciousKey; // accepts a callback with prototype like
// void keypressed();
};
GUI_APP_MAIN
{
MainWindow m;
m.WhenSuspiciousKey<<[]{ PromptOK("Use upper case W,A,S,D to navigate!");};
m.Run();
//
// MainWindow *m=new MainWindow;
// m->OpenMain();
//// m->SetFocus();
//// DUMP(m->HasFocus());
// Ctrl::EventLoop();
}
BTW, there is nothing wrong with allocating your MainWindow or other Ctrls from stack. But in U++, you don't have to. In your case, there is no reason to do it that way.
[Updated on: Sat, 18 December 2021 05:43] Report message to a moderator
|
|
|
Re: Focus problem [message #57805 is a reply to message #57799] |
Sat, 18 December 2021 16:03   |
Silvan
Messages: 56 Registered: December 2014 Location: Trento (IT)
|
Member |
|
|
Thank you Lance,
understood and it solve all my inizial problem.
And what about if would like to do something like this:
MainWindow()
{
Title("Test Focus").Zoomable().Sizeable();
Add(inputtext.TopPosZ(0, 16).HSizePos());
Add(panel.VSizePos(18, 0).HSizePos(0, 0));
inputtext <<= "test";
ActiveFocus(panel);
panel.Paint << [&](Draw &w) { w.DrawText(p.x, p.y, "#", Arial(30), Red);};
panel.Key << [&](dword key, int count) { switch (key) { /
case K_W: /
p.y-=1; /
break; /
case K_S: /
p.y+=1; /
break; /
case K_A: /
p.x-=1; /
break; /
case K_D: /
p.x+=1; /
break; /
default: /
; /
} /
Refresh(); return true; }; /
SetRect(0, 0, 300, 300);
p.x = 150;
p.y = 150;
}
};
This code does not compile.... I would override directy the method and event of ImageCtrl panel.
How this is possible?
Thank you
Silvan
|
|
|
|
|
|
Re: Focus problem [message #57809 is a reply to message #57784] |
Sat, 18 December 2021 18:32   |
Silvan
Messages: 56 Registered: December 2014 Location: Trento (IT)
|
Member |
|
|
Hi Lance,
I understand the cost, but my code above does not compile.
How can I specify a code for an event or a method for a Ctrl?
I'm a C low level programmer and I really like U++ and sometimes I use it
for front end gui stuff.
I suppose there should be some direct way to define the code for event and method?
Similar to C#, ore VCL.
Or that is not possible for permormance reason?
Thank you
PS: I clarify better my doubt.
There are plenty of example that show how simple and fast is to program the U++ GUI framework by easily define your handler to event and method.
But they always refers to TopWindows or menu or statusbar (using overrid) , I can't find an example for other gadget like ImageCtrl.
Maybe I'm confused by the sentence that told THISBACK is deprecated, maybe that is the simplest way. But I'm now confused.
[Updated on: Sat, 18 December 2021 21:55] Report message to a moderator
|
|
|
Re: Focus problem [message #57812 is a reply to message #57784] |
Sun, 19 December 2021 12:23   |
Silvan
Messages: 56 Registered: December 2014 Location: Trento (IT)
|
Member |
|
|
Here is a working code as intended:
some thought:
1) I used a new class derived from ImageCtrl, I suppose that is a little bit overkill for a simply overload of two method/event;
2) I had to use a global variable (Point p) otherwise not accessible from the new class Mypanel. Really bad.
3) I had to use the override Close method otherwise the program terminate with an error.
I suppose that U++ allow to do all this much better... I'm searching how hoping in some help!
Thank you
Silvan
#include <CtrlLib/CtrlLib.h>
using namespace Upp;
Point p;
struct MyPanel : ImageCtrl {
virtual void Paint(Draw& w)override
{
w.DrawRect(GetSize(), White());
w.DrawText(p.x, p.y, "#", Arial(30), Red);
Refresh();
}
virtual bool Key(dword key, int count) override
{
switch (key)
{
case K_W:
p.y-=1;
break;
case K_S:
p.y+=1;
break;
case K_A:
p.x-=1;
break;
case K_D:
p.x+=1;
break;
default:
;
}
Refresh();
return true;
}
void LeftDown(Point p, dword keyflags) override
{
SetFocus();
}
};
struct MainWindow : TopWindow {
EditString inputtext;
MyPanel panel;
void Close() override
{
delete this;
}
// Costruttore dove inserisci le inizializzazioni
MainWindow()
{
Title("Test Focus").Zoomable().Sizeable();
Add(inputtext.TopPosZ(0, 16).HSizePos());
Add(panel.VSizePos(26, 0).HSizePos(0, 0));
inputtext <<= "test";
SetRect(0, 0, 300, 300);
p.x = 150;
p.y = 150;
}
};
GUI_APP_MAIN
{
(new MainWindow)->OpenMain();
Ctrl::EventLoop();
}
|
|
|
Re: Focus problem [message #57816 is a reply to message #57812] |
Sun, 19 December 2021 14:22   |
Lance
Messages: 656 Registered: March 2007
|
Contributor |
|
|
Hi Silvan:
The way I define WhenSuspiciousKey is a typical way to define an Event. First, the Ctrl or its direvative need to provide a chance for the event in a (relevant) overrided virtual function. In my case, I overrided
In my MainWindow::Key(...)
I allowed WhenSuspiciousKey be called at certain time. What is WhenSuspiciousKey? I define it as a member variable of MainWindow of type Event<>
By add this member variable to MainWindow, the user of MainWindow can assign a callback to an instance(object) of this type by
MainWindow m;
m<<[]{...};
There is no magic here. C have simlar (but much limited ) mechanism. WhenSuspiciousKey is like a function pointer to which you can assign a callback. In order for this callback to actually be called, some where, you need to check and call it(in our case, it's in the MainWindow::Key(...) virtual function).
Now, Key is a virtual function, you cannot assign a callback to it. On the other hand, an object of MainWindow, m, has a public member variable name WhenSuspciciousKey, which is of type Event<>. You can access this member variable. One way is by something like
m.WhenSuspiciousKey<<[]{};
-----
PS: On a second thought, use C function pointer as example:
void (*WhenWhat)(int);
void func1(int p)
{
if(WhenWhat)
WhenWhat(p);
}
void callback(int p)
{
}
WhenWhat=callback; // this is good
// just like
// WhenSuspiciousKey<<[]{};
// is fine
func1=callback; // this won't compile
// just like
// Key<<[]{};
// won't compile.
[Updated on: Sun, 19 December 2021 15:02] Report message to a moderator
|
|
|
Re: Focus problem [message #57817 is a reply to message #57812] |
Sun, 19 December 2021 14:31   |
Lance
Messages: 656 Registered: March 2007
|
Contributor |
|
|
1): Derive MyPanel from ImageCtrl to supply customized Paint and Key is the right thing to do, at the moment at least, unfortunately.
3): Overriding MyPanel::Close to delete this is unnecessary and considered bad practice (in this case at least).
By overriding MyPanel::Close in your way, you basically enforce that MyPanel object have be be allocated from heap. U++ doesn't prohibit you from allocating Ctrl derivatives from heap, but it's much more often we have its object contained and be allocated from stack(faster and less memory usage). Or it can even be global, static etc.
In your case, if you really want your object be allocated from heap, you can use U++ provided smart pointer One to manage it for you. See example in the next reply.
[Updated on: Sun, 19 December 2021 15:26] Report message to a moderator
|
|
|
Re: Focus problem [message #57818 is a reply to message #57817] |
Sun, 19 December 2021 14:44   |
Lance
Messages: 656 Registered: March 2007
|
Contributor |
|
|
2): put
as global is unnecessary and highly likely conceptually wrong: what if you want multiple but independent windows who need to maintain their own current positions?.
The following revised code takes care of that, also demonstrate a simple use of One.
U++ is created by powerful programmers who actually use it. There are a lot of convenience utilities like One,DUMP,LOG, etc (I don't know many either, but read U++ source code, read old posts, etc and build up this knowledge; it will significantly increase your productivity: almost in all situation you need a specific tool or facility, someone before you has encounter it and figure out a smart solution).
BTW, welcome to U++ community!
#include <CtrlLib/CtrlLib.h>
using namespace Upp;
struct MyPanel : ImageCtrl {
Point p;
virtual void Paint(Draw& w)override
{
w.DrawRect(GetSize(), White());
w.DrawText(p.x, p.y, "#", Arial(30), Red);
Refresh();
}
virtual bool Key(dword key, int count) override
{
switch (key)
{
case K_W:
p.y-=1;
break;
case K_S:
p.y+=1;
break;
case K_A:
p.x-=1;
break;
case K_D:
p.x+=1;
break;
default:
;
}
Refresh();
return true;
}
void LeftDown(Point p, dword keyflags) override
{
SetFocus();
}
};
struct MainWindow : TopWindow {
EditString inputtext;
MyPanel panel;
// void Close() override
// {
// delete this;
// }
// Costruttore dove inserisci le inizializzazioni
MainWindow()
{
Title("Test Focus").Zoomable().Sizeable();
Add(inputtext.TopPosZ(0, 16).HSizePos());
Add(panel.VSizePos(26, 0).HSizePos(0, 0));
inputtext <<= "test";
SetRect(0, 0, 300, 300);
panel.p.x = 150;
panel.p.y = 150;
}
};
GUI_APP_MAIN
{
// dynamically allocated MainWindow
One<MainWindow> m;
m.Create<MainWindow>().OpenMain();
// allocated from Stack.
MainWindow().OpenMain();
// because now Point p is per instance (not global)
// you can control each independent of the other.
//(new MainWindow)->OpenMain();
Ctrl::EventLoop();
}
[Updated on: Sun, 19 December 2021 15:30] Report message to a moderator
|
|
|
Re: Focus problem [message #57823 is a reply to message #57817] |
Sun, 19 December 2021 15:37   |
Silvan
Messages: 56 Registered: December 2014 Location: Trento (IT)
|
Member |
|
|
Lance wrote on Sun, 19 December 2021 14:311): Derive MyPanel from ImageCtrl to supply customized Paint and Key is the right thing to do, at the moment at least, unfortunately.
3): Overriding MyPanel::Close to delete this is unnecessary and considered bad practice (in this case at least).
By overriding MyPanel::Close in your way, you basically enforce that MyPanel object have be be allocated from heap. U++ doesn't prohibit you from allocating Ctrl derivatives from heap, but it's much more often we have its object contained and be allocated from stack(faster and less memory usage). Or it can even be global, static etc.
In your case, if you really want your object be allocated from heap, you can use U++ provided smart pointer One to manage it for you. See example in the next reply.
If I comment out MainWindows::Close (not MyPanel) than when I exit the program there is an exception at address .....
That appens with:
(new MainWindow)->OpenMain();
Ctrl::EventLoop();
With:
I can comment out Close whitout error on exiting.
[Updated on: Sun, 19 December 2021 15:47] Report message to a moderator
|
|
|
|
|
|
|
|
Goto Forum:
Current Time: Tue Apr 29 01:41:37 CEST 2025
Total time taken to generate the page: 0.01215 seconds
|
|
|