|
|
Home » Developing U++ » U++ Developers corner » Using Pen with U++
|
Re: Using Pen with U++ [message #56549 is a reply to message #56548] |
Wed, 24 March 2021 15:56 |
|
mirek
Messages: 13975 Registered: November 2005
|
Ultimate Member |
|
|
Tom1 wrote on Wed, 24 March 2021 15:21OK, I see. I'll give it a try... (will return soon.)
Best regards,
Tom
Well, I thought I will do that tonight or tomorrow, but if you want to try, there are some tips and tricks how I planned to do it:
- add another kind of event PEN 0xf0 after TRIPLE constant
- will need to add handling in DoMouse around CtrlCore/CtrlMouse.cpp:149
- we will need to somehow return that bool; DoMouse returns Image, here I planned to use a trick to return Null or Non-null image to signal true-falase (use any image available)
- as for Pen signature, I was thinking about creating some struct type with all the information (pressure, tilt etc) that would be passed as parameter. Perhaps leave Point as separate parameter. So something like
virtual bool Pen(Point p, const PenInfo& f);
Mirek
|
|
|
Re: Using Pen with U++ [message #56550 is a reply to message #56549] |
Wed, 24 March 2021 16:51 |
Tom1
Messages: 1212 Registered: March 2007
|
Senior Contributor |
|
|
Mirek,
I was only thinking about declaring:
virtual bool PenDown(Point p, dword keyflags){ return false; }
virtual bool PenUp(Point p, dword keyflags){ return false; }
virtual bool PenMove(Point p, dword keyflags){ return false; }
and calling them directly like this
switch(message) {
case WM_POINTERDOWN:
ClickActivateWnd();
if(PenDown(Point(p), GetMouseFlags())) return 0L;
break;
case WM_POINTERUP:
if(PenUp(Point(p), GetMouseFlags())) return 0L;
break;
case WM_POINTERUPDATE:
if(PenMove(Point(p), GetMouseFlags())) return 0L;
break;
}
break;
...and using the Pen -functions you made earlier.
However, my simple approach above would inevitably have its shortcomings as properly tracking the pen/mouse position (e.g. GetMousePos()) cannot be taken care of this way. RectTracker would likely also be broken in this case.
Despite working several tens of hours on this, my understanding on Ctrl and mouse processing is not sufficient yet to do it the right way. (Despite the several tens of hours I have spent on this during the few last days. Shame on me.)
So, absolutely, if you have time, please do it the right way. (I have a strong feeling that it will eventually save time for both of us.)
In any case, I'll be here ready to test as soon as you post an update.
Best regards,
Tom
EDIT: BTW: How did you think about handling barrel-button and other flags? After playing around with the pen, I have noticed that it is very difficult to click barrel and other buttons on the pen while keeping it steady. So, IMO, barrel should be just a flag to read when pen goes down/up or moves. Just like Shift/Ctrl/Alt, which are used and needed as modifiers similarly for pen and mouse.
Also, I feel PenMove + PenDown + PenUp make it easier to write code for the pen, instead of a single PenUpdate function.
Further on, readily supporting PenHold, PenDouble (and possibly PenTriple) would be useful. Decoding them in application would require passing timestamps too, which is not very convenient.
EDIT2: Actually, I would rather have PEN defined as 3 or 4, i.e. in parallel to LEFT, RIGHT and MIDDLE. This way we can have PEN|DOWN, PEN|UP, PEN|DOUBLE, ... and just PEN for move.
[Updated on: Wed, 24 March 2021 17:27] Report message to a moderator
|
|
|
Re: Using Pen with U++ [message #56551 is a reply to message #56550] |
Wed, 24 March 2021 18:01 |
|
mirek
Messages: 13975 Registered: November 2005
|
Ultimate Member |
|
|
Tom1 wrote on Wed, 24 March 2021 16:51Mirek,
I was only thinking about declaring:
virtual bool PenDown(Point p, dword keyflags){ return false; }
virtual bool PenUp(Point p, dword keyflags){ return false; }
virtual bool PenMove(Point p, dword keyflags){ return false; }
and calling them directly like this
switch(message) {
case WM_POINTERDOWN:
ClickActivateWnd();
if(PenDown(Point(p), GetMouseFlags())) return 0L;
break;
case WM_POINTERUP:
if(PenUp(Point(p), GetMouseFlags())) return 0L;
break;
case WM_POINTERUPDATE:
if(PenMove(Point(p), GetMouseFlags())) return 0L;
break;
}
break;
...and using the Pen -functions you made earlier.
This would not work - only top level windows are receiving messages from Win32. DoMouse then distributes them to target widgets (with a ton of logic and coordinate translations involved).
Quote:
EDIT: BTW: How did you think about handling barrel-button and other flags? After playing around with the pen, I have noticed that it is very difficult to click barrel and other buttons on the pen while keeping it steady. So, IMO, barrel should be just a flag to read when pen goes down/up or moves. Just like Shift/Ctrl/Alt, which are used and needed as modifiers similarly for pen and mouse.
As flag in PenInfo. That is the reason I vote for structure passed so that it can be extended.
Quote:
Also, I feel PenMove + PenDown + PenUp make it easier to write code for the pen, instead of a single PenUpdate function.
IDK. I feel like pen actually would be better handled with single method. I guess I have to try.
Mirek
|
|
|
Re: Using Pen with U++ [message #56552 is a reply to message #56551] |
Wed, 24 March 2021 18:22 |
Tom1
Messages: 1212 Registered: March 2007
|
Senior Contributor |
|
|
OK. PenInfo structure sounds good.
Please include 'dword keyflags' in call parameters or PenInfo.
Also, if you end up with a single method like 'PenUpdate()' or whatever, please also include reason = MOVE/DOWN/UP/HOLD/DOUBLE/... in call parameters or PenInfo.
Thanks and best regards,
Tom
|
|
|
Re: Using Pen with U++ [message #56564 is a reply to message #56552] |
Thu, 25 March 2021 19:58 |
|
mirek
Messages: 13975 Registered: November 2005
|
Ultimate Member |
|
|
First attempt commited.
#include <CtrlLib/CtrlLib.h>
using namespace Upp;
struct MyApp : TopWindow {
Point pos;
Vector<Vector<Tuple<double, Pointf>>> drawing;
PenInfo pen;
virtual bool Pen(Point p, const PenInfo& pn, dword keyflags) {
if(pn.pressure) {
if((!!pn.pressure == !!pen.pressure) && drawing.GetCount())
drawing.Top().Add(MakeTuple(pn.pressure, p));
else
drawing.Add().Add(MakeTuple(pn.pressure, p));
}
pen = pn;
Refresh();
return true;
}
virtual void Paint(Draw& w0) {
DrawPainter w(w0, GetSize());
w.Co();
w.Clear(SColorPaper());
w.LineCap(LINECAP_ROUND);
for(const auto& stroke : drawing)
if(stroke.GetCount())
for(int i = 0; i < stroke.GetCount() - 1; i++) {
w.Move(stroke[i].b);
w.Line(stroke[i + 1].b);
w.Stroke(DPI(20) * stroke[i].a, Black());
}
int fcy = GetStdFontCy();
int y = 10;
auto Text = [&] (const String& text) {
w.DrawText(10, y, text);
y += fcy;
};
Text(AsString(pos));
Text(String() << "Pressure: " << pen.pressure);
Text(String() << "Rotation: " << pen.rotation);
Text(String() << "Tilt: " << pen.tilt);
Text(String() << "Barrel: " << pen.barrel);
Text(String() << "Inverted: " << pen.inverted);
Text(String() << "Eraser: " << pen.eraser);
}
};
GUI_APP_MAIN
{
MyApp().Run();
}
|
|
|
Re: Using Pen with U++ [message #56565 is a reply to message #56564] |
Thu, 25 March 2021 20:47 |
Tom1
Messages: 1212 Registered: March 2007
|
Senior Contributor |
|
|
Hi Mirek,
And thanks for the first round on the new Pen interface.
The standard controls seem to work correctly (as expected) and the new interface is nice and clean.
However, the RectTracker needs attention. Please add the following code to the test case and see what happens with Ctrl+Pen and Shift+Pen:
virtual bool Pen(Point p, const PenInfo& pn, dword keyflags) {
if(pn.action==PEN_DOWN){
if(keyflags&K_SHIFT){
RectTracker tracker(*this);
tracker.sync= [=](Rect r) { };
tracker.MinSize(Size(-100000,-100000));
tracker.Track(Rect(p,p));
}
else if(keyflags&K_CTRL){
RectTracker tracker(*this);
tracker.TrackLine(p.x,p.y);
}
}
if(pn.pressure) {
if((!!pn.pressure == !!pen.pressure) && drawing.GetCount())
drawing.Top().Add(MakeTuple(pn.pressure, p));
else
drawing.Add().Add(MakeTuple(pn.pressure, p));
}
pen = pn;
Refresh();
return true;
}
Thanks and best regards,
Tom
|
|
|
Re: Using Pen with U++ [message #56567 is a reply to message #56565] |
Thu, 25 March 2021 22:07 |
|
mirek
Messages: 13975 Registered: November 2005
|
Ultimate Member |
|
|
Well, I will try to make it work, however the indended road was something like
virtual bool Pen(Point p, const PenInfo& pn, dword keyflags) {
if(keyflags&K_SHIFT)
return false;
if(pn.pressure) {
if((!!pn.pressure == !!pen.pressure) && drawing.GetCount())
drawing.Top().Add(MakeTuple(pn.pressure, p));
else
drawing.Add().Add(MakeTuple(pn.pressure, p));
}
pen = pn;
Refresh();
return true;
}
void LeftDown(Point p, dword keyflags) override {
if(keyflags & K_SHIFT) {
RectTracker tracker(*this);
tracker.MinSize(Size(-100000,-100000));
tracker.Track(Rect(p,p));
}
}
|
|
|
Re: Using Pen with U++ [message #56568 is a reply to message #56565] |
Thu, 25 March 2021 22:28 |
Tom1
Messages: 1212 Registered: March 2007
|
Senior Contributor |
|
|
Mirek,
Is pn.action intentionally merely a state flag showing continuously PEN_UP or PEN_DOWN? Or should we reset it along with other PenInfo items in the beginning of processing WM_POINTER* messages?
I would like to have it reset, in order to more easily detect UP/DOWN state changes without a state variable and treat zero action as 'PEN_MOVE'.
Then we could do this to decode all kinds of pen events:
#define PENMOVE 0
#define PENDOWN 1
#define PENUP 2
#define PENHOLD 3
#define PENDRAG 4
#define PENDOUBLE 5
#define PENTRIPLE 6
bool IsNear(Point p, Point o){
Point delta(p-o);
if(abs(delta.x)<5 && abs(delta.y)<5) return true;
return false;
}
int PenDecoder(Point p, const PenInfo& pn, dword keyflags){
static int action=0;
static int downt=0;
static Point downp=Null;
static bool doubleClick=true;
static bool down=false;
static bool solved=false;
int now=msecs();
int deltat=now-downt;
bool isNear=IsNear(p,downp);
switch(pn.action){
case PEN_DOWN:
down=true;
solved=false;
downp=p;
downt=now;
if(isNear){
if(now-downt < 500){
if(doubleClick){
return PENTRIPLE;
}
else{
doubleClick=true;
return PENDOUBLE;
}
}
}
doubleClick=false;
return PENDOWN;
case PEN_UP:
down=false;
return PENUP;
default:
if(down && !solved){
if(isNear){
if(now-downt > 1000){
solved=true;
return PENHOLD;
}
}
else{
solved=true;
return PENDRAG;
}
}
return PENMOVE;
}
}
Best regards,
Tom
|
|
|
Re: Using Pen with U++ [message #56569 is a reply to message #56567] |
Thu, 25 March 2021 22:33 |
Tom1
Messages: 1212 Registered: March 2007
|
Senior Contributor |
|
|
mirek wrote on Thu, 25 March 2021 23:07Well, I will try to make it work, however the indended road was something like
virtual bool Pen(Point p, const PenInfo& pn, dword keyflags) {
if(keyflags&K_SHIFT)
return false;
if(pn.pressure) {
if((!!pn.pressure == !!pen.pressure) && drawing.GetCount())
drawing.Top().Add(MakeTuple(pn.pressure, p));
else
drawing.Add().Add(MakeTuple(pn.pressure, p));
}
pen = pn;
Refresh();
return true;
}
void LeftDown(Point p, dword keyflags) override {
if(keyflags & K_SHIFT) {
RectTracker tracker(*this);
tracker.MinSize(Size(-100000,-100000));
tracker.Track(Rect(p,p));
}
}
Previous message content cleared.
Issue solved: I will return with a working RectTracker solution in the next message.
Best regards,
Tom
[Updated on: Fri, 26 March 2021 00:15] Report message to a moderator
|
|
|
Re: Using Pen with U++ [message #56571 is a reply to message #56569] |
Fri, 26 March 2021 00:22 |
Tom1
Messages: 1212 Registered: March 2007
|
Senior Contributor |
|
|
OK, here are all the RectTracker changes required:
Add in RectTracker:: in CtrlCore.h:
virtual bool Pen(Point p, const PenInfo& pn, dword keyflags);
Add in LocalLoop.cpp:
bool RectTracker::Pen(Point p, const PenInfo& pn, dword keyflags){
switch(pn.action){
default:
MouseMove(p, keyflags);
break;
case PEN_UP:
LeftUp(p, keyflags);
break;
}
return true;
}
And finally changes in Win32Proc.cpp:
...
static bool pendown=false;
bool GetShift() { return !!(GetKeyStateSafe(VK_SHIFT) & 0x8000); }
bool GetCtrl() { return !!(GetKeyStateSafe(VK_CONTROL) & 0x8000); }
bool GetAlt() { return !!(GetKeyStateSafe(VK_MENU) & 0x8000); }
bool GetCapsLock() { return !!(GetKeyStateSafe(VK_CAPITAL) & 1); }
bool GetMouseLeft() { return pendown || !!(GetKeyStateSafe(VK_LBUTTON) & 0x8000); }
bool GetMouseRight() { return !!(GetKeyStateSafe(VK_RBUTTON) & 0x8000); }
bool GetMouseMiddle() { return !!(GetKeyStateSafe(VK_MBUTTON) & 0x8000); }
bool PassWindowsKey(int wParam);
LRESULT Ctrl::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) {
GuiLock __;
eventid++;
// LLOG("Ctrl::WindowProc(" << message << ") in " << ::Name(this) << ", focus " << (void *)::GetFocus());
Ptr<Ctrl> _this = this;
HWND hwnd = GetHWND();
switch(message) {
case WM_POINTERDOWN:
case WM_POINTERUPDATE:
case WM_POINTERUP: {
pen.action = 0;
pen.pressure = pen.rotation = Null;
pen.tilt = Null;
pen.eraser = pen.barrel = pen.inverted = pen.history = false;
static BOOL (WINAPI *GetPointerType)(UINT32 pointerId, POINTER_INPUT_TYPE *pointerType);
static BOOL (WINAPI *GetPointerInfo)(UINT32 pointerId, POINTER_INFO *pointerInfo);
static BOOL (WINAPI *GetPointerPenInfo)(UINT32 pointerId, POINTER_PEN_INFO *penInfo);
static BOOL (WINAPI *GetPointerPenInfoHistory)(UINT32 pointerId, UINT32 *entriesCount, POINTER_PEN_INFO *penInfo);
ONCELOCK {
DllFn(GetPointerType, "User32.dll", "GetPointerType");
DllFn(GetPointerInfo, "User32.dll", "GetPointerInfo");
DllFn(GetPointerPenInfo, "User32.dll", "GetPointerPenInfo");
DllFn(GetPointerPenInfoHistory, "User32.dll", "GetPointerPenInfoHistory");
};
if(!(GetPointerType && GetPointerInfo && GetPointerPenInfo && GetPointerPenInfoHistory))
break;
POINTER_INPUT_TYPE pointerType;
auto ProcessPenInfo = [&] (POINTER_PEN_INFO& ppi) {
if(ppi.penFlags & PEN_FLAG_BARREL)
pen.barrel = true;
if(ppi.penFlags & PEN_FLAG_INVERTED)
pen.inverted = true;
if(ppi.penFlags & PEN_FLAG_ERASER)
pen.eraser = true;
if(ppi.penMask & PEN_MASK_PRESSURE)
pen.pressure = ppi.pressure / 1024.0;
if(ppi.penMask & PEN_MASK_ROTATION)
pen.rotation = ppi.rotation * M_2PI / 360;
if(ppi.penMask & PEN_MASK_TILT_X)
pen.tilt.x = ppi.tiltX * M_2PI / 360;
if(ppi.penMask & PEN_MASK_TILT_Y)
pen.tilt.y = ppi.tiltY * M_2PI / 360;
};
UINT32 pointerId = GET_POINTERID_WPARAM(wParam);
if(GetPointerType(pointerId, &pointerType) && pointerType == PT_PEN) {
UINT32 hc = 256;
Buffer<POINTER_PEN_INFO> ppit(hc);
if(message == WM_POINTERUPDATE && GetPointerPenInfoHistory(pointerId, &hc, ppit)) {
bool processed = false;
for(int i = hc - 1; i >= 0; i--) {
ProcessPenInfo(ppit[i]);
POINT hp = ppit[i].pointerInfo.ptPixelLocation;
::SetCursorPos(hp.x,hp.y);
::ScreenToClient(hwnd, &hp);
pen.history = (bool)i;
processed = !IsNull(DoMouse(PEN, hp, 0));
}
if(processed)
return 0L;
else
break;
}
POINTER_PEN_INFO ppi;
if(GetPointerPenInfo(pointerId, &ppi))
ProcessPenInfo(ppi);
POINT p = ppi.pointerInfo.ptPixelLocation;
::SetCursorPos(p.x,p.y);
::ScreenToClient(hwnd, &p);
switch(message) {
case WM_POINTERDOWN:
pendown=true;
pen.action = PEN_DOWN;
ClickActivateWnd();
break;
case WM_POINTERUP:
pendown=false;
pen.action = PEN_UP;
break;
}
if(!IsNull(DoMouse(PEN, p, 0)))
return 0L;
break;
}
}
break;
...
The main problem was that ::GetCursorPos() was not working as ::SetCursorPos() was not called from WM_POINTER*. Now it all works and mouse follows pen.
Best regards,
Tom
EDIT: Not quite... calling SetCursorPos() causes incoming WM_MOUSEMOVE messages at some frequency, but the coordinates are obviously old ones causing erratic behavior if both MouseMove and Pen are processed... However, if SetCursorPos() is not called, the mouse position will be different to pen and it will in turn cause flickering RectTracker with intermediate rectangles to mouseposition!
Well, I'm done for today. (or yesterday, or whatever.) Anyway, if you have any ideas how to go around this, please fill in...
[Updated on: Fri, 26 March 2021 01:02] Report message to a moderator
|
|
|
Re: Using Pen with U++ [message #56573 is a reply to message #56568] |
Fri, 26 March 2021 08:57 |
|
mirek
Messages: 13975 Registered: November 2005
|
Ultimate Member |
|
|
Tom1 wrote on Thu, 25 March 2021 22:28Mirek,
Is pn.action intentionally merely a state flag showing continuously PEN_UP or PEN_DOWN? Or should we reset it along with other PenInfo items in the beginning of processing WM_POINTER* messages?
I would like to have it reset, in order to more easily detect UP/DOWN state changes without a state variable and treat zero action as 'PEN_MOVE'.
Then we could do this to decode all kinds of pen events:
#define PENMOVE 0
#define PENDOWN 1
#define PENUP 2
#define PENHOLD 3
#define PENDRAG 4
#define PENDOUBLE 5
#define PENTRIPLE 6
bool IsNear(Point p, Point o){
Point delta(p-o);
if(abs(delta.x)<5 && abs(delta.y)<5) return true;
return false;
}
int PenDecoder(Point p, const PenInfo& pn, dword keyflags){
static int action=0;
static int downt=0;
static Point downp=Null;
static bool doubleClick=true;
static bool down=false;
static bool solved=false;
int now=msecs();
int deltat=now-downt;
bool isNear=IsNear(p,downp);
switch(pn.action){
case PEN_DOWN:
down=true;
solved=false;
downp=p;
downt=now;
if(isNear){
if(now-downt < 500){
if(doubleClick){
return PENTRIPLE;
}
else{
doubleClick=true;
return PENDOUBLE;
}
}
}
doubleClick=false;
return PENDOWN;
case PEN_UP:
down=false;
return PENUP;
default:
if(down && !solved){
if(isNear){
if(now-downt > 1000){
solved=true;
return PENHOLD;
}
}
else{
solved=true;
return PENDRAG;
}
}
return PENMOVE;
}
}
Best regards,
Tom
Would it solve any real problem? I mean, I believe that the application can do all these on its own, if it needs to.
|
|
|
Re: Using Pen with U++ [message #56576 is a reply to message #56573] |
Fri, 26 March 2021 10:15 |
Tom1
Messages: 1212 Registered: March 2007
|
Senior Contributor |
|
|
Hi,
Well, I put the 'PenDecoder' here just for reference for anyone wishing to map pen to mouse like callbacks in application. It does not really need to be part of CtrlCore.
However, my point here is that, I would feel more at home, if:
- only WM_POINTERUP would cause pn.action=PEN_UP
- only WM_POINTERDOWN would cause pn.action=PEN_DOWN
- and WM_POINTERUPDATE would always keep pn.action=0; (or PEN_MOVE).
I.e. pn.action would be event type instead of state flag of up/down status.
Or do you have some particular reason to always have pn.action set to either PEN_UP or PEN_DOWN depepending on the last change?
Best regards,
Tom
|
|
|
|
|
Re: Using Pen with U++ [message #56583 is a reply to message #56581] |
Fri, 26 March 2021 15:05 |
Novo
Messages: 1358 Registered: December 2006
|
Ultimate Contributor |
|
|
Linux, Clang:
./umk uppsrc ide CLANG -bus
/home/buildbot/worker/l-upp/build/uppsrc/CtrlCore/GtkEvent.cpp:429:6: error: no viable overloaded '='
pen = CurrentEvent.pen;
~~~ ^ ~~~~~~~~~~~~~~~~
Regards,
Novo
|
|
|
Re: Using Pen with U++ [message #56584 is a reply to message #56583] |
Fri, 26 March 2021 15:08 |
Novo
Messages: 1358 Registered: December 2006
|
Ultimate Contributor |
|
|
Alpine Linux (in addition to previous error):
./umk uppsrc ide CLANG -bus
/home/buildbot/worker/al-upp/build/uppsrc/CtrlCore/GtkEvent.cpp:430:2: error: use of undeclared identifier 'pen_barrel'
pen_barrel = CurrentEvent.pen_barrel;
^
/home/buildbot/worker/al-upp/build/uppsrc/CtrlCore/GtkEvent.cpp:431:2: error: use of undeclared identifier 'pen_inverted'
pen_inverted = CurrentEvent.pen_inverted;
^
/home/buildbot/worker/al-upp/build/uppsrc/CtrlCore/GtkEvent.cpp:432:2: error: use of undeclared identifier 'pen_eraser'
pen_eraser = CurrentEvent.pen_eraser;
^
/home/buildbot/worker/al-upp/build/uppsrc/CtrlCore/GtkEvent.cpp:433:2: error: use of undeclared identifier 'pen_pressure'
pen_pressure = CurrentEvent.pen_pressure;
^
/home/buildbot/worker/al-upp/build/uppsrc/CtrlCore/GtkEvent.cpp:434:2: error: use of undeclared identifier 'pen_rotation'
pen_rotation = CurrentEvent.pen_rotation;
^
/home/buildbot/worker/al-upp/build/uppsrc/CtrlCore/GtkEvent.cpp:435:2: error: use of undeclared identifier 'pen_tilt'
pen_tilt = CurrentEvent.pen_tilt;
^
Regards,
Novo
|
|
|
|
Re: Using Pen with U++ [message #56590 is a reply to message #56585] |
Fri, 26 March 2021 16:44 |
Tom1
Messages: 1212 Registered: March 2007
|
Senior Contributor |
|
|
Mirek,
'case PEN_OTHER:' Looks better than 'case 0:' ...
Quote:Is it so bad to just leave it to LeftDown?
I'm not quite sure what do you mean by this.. (?) (If it is about double clicks, drags or barrel mappings to right mouse button, I can handle them in the application side.)
--
Anyway, now the good news: I finally got through with RectTracker and Get/SetCursorPos.
The set of changes required follow.
Add to CtrlCore.h:
bool GetPenDown(); // << ADD THIS
... AND ...
class RectTracker : public LocalLoop {
public:
virtual void LeftUp(Point, dword);
virtual void RightUp(Point, dword);
virtual void MouseMove(Point p, dword);
virtual bool Pen(Point p, const PenInfo& pn, dword keyflags); // << ADD THIS
Add "&& !GetPenDown()" at line 595 in CtrlMouse.cpp:
...
if(findarg(e, LEFTUP, RIGHTUP, MIDDLEUP) >= 0)
KillRepeat();
Image result = DispatchMouseEvent(e, p, zd);
if(!GetMouseRight() && !GetMouseMiddle() && !GetMouseLeft() && !GetPenDown())
ReleaseCtrlCapture();
return result;
...
Add to LocalLoop.cpp:
bool RectTracker::Pen(Point p, const PenInfo& pn, dword keyflags){
switch(pn.action){
case 0:
MouseMove(p,keyflags);
break;
case PEN_UP:
EndLoop();
break;
}
return true;
}
Add "&& !GetPenDown()" at line 781 in Win32Wnd.cpp:
...
bool Ctrl::ProcessEvent(bool *quit)
{
ASSERT_(IsMainThread(), "ProcessEvent can only run in the main thread");
if(!GetMouseLeft() && !GetMouseRight() && !GetMouseMiddle() && !GetPenDown()) // << HERE
ReleaseCtrlCapture();
...
And the rest is in the attached Win32Proc.cpp.
Best regards,
Tom
[Updated on: Fri, 26 March 2021 19:25] Report message to a moderator
|
|
|
Re: Using Pen with U++ [message #56592 is a reply to message #56590] |
Fri, 26 March 2021 18:19 |
|
mirek
Messages: 13975 Registered: November 2005
|
Ultimate Member |
|
|
Tom1 wrote on Fri, 26 March 2021 16:44Mirek,
'case PEN_OTHER:' Looks better than 'case 0:' ...
'default:' is fine too
Quote:
Quote:Is it so bad to just leave it to LeftDown?
I'm not quite sure what do you mean by this.. (?) (If it is about double clicks, drags or barrel mappings to right mouse button, I can handle them in the application side.)
bool Pen(Point p, const PenInfo& pn, dword keyflags) override {
if(keyflags & K_SHIFT)
return false;
if(pn.pressure) {
if((!!pn.pressure == !!pen.pressure) && drawing.GetCount())
drawing.Top().Add(MakeTuple(pn.pressure, p));
else
drawing.Add().Add(MakeTuple(pn.pressure, p));
}
pen = pn;
Refresh();
return true;
}
void LeftDown(Point p, dword keyflags) override {
if(keyflags & K_SHIFT) {
RectTracker tracker(*this);
tracker.MinSize(Size(-100000,-100000));
tracker.Track(Rect(p,p));
}
}
I mean, the main reason for separated Pen method interface is that we do not want to add support to any client code. So to start adding just that right away is perhaps not the best idea?
Mirek
[Updated on: Fri, 26 March 2021 18:21] Report message to a moderator
|
|
|
Goto Forum:
Current Time: Wed Apr 24 13:17:48 CEST 2024
Total time taken to generate the page: 0.03667 seconds
|
|
|