Overview
Examples
Screenshots
Comparisons
Applications
Download
Documentation
Tutorials
Bazaar
Status & Roadmap
FAQ
Authors & License
Forums
Funding Ultimate++
Search on this site
Search in forums












SourceForge.net Logo
Home » Developing U++ » U++ Developers corner » Using Pen with U++
Re: Using Pen with U++ [message #56434 is a reply to message #56433] Thu, 11 March 2021 14:41 Go to previous messageGo to next message
Tom1
Messages: 1212
Registered: March 2007
Senior Contributor
Actually you do get those WM_POINTERDOWN and WM_POINTERUP. From your log:
WM_POINTERUPDATE
WM_POINTERUPDATE
WM_MOUSEMOVE
WM_POINTERUPDATE
WM_POINTERDOWN   <<< HERE
WM_MOUSEMOVE
WM_POINTERUPDATE
WM_POINTERUPDATE
WM_POINTERUPDATE
WM_POINTERUPDATE
WM_POINTERUPDATE
WM_POINTERUPDATE
WM_LBUTTONDOWN
Start line
WM_MOUSEMOVE
Drawing line, pressure: 0.109375
WM_POINTERUPDATE
WM_MOUSEMOVE
Drawing line, pressure: 0.12890625

...

WM_POINTERUPDATE
WM_MOUSEMOVE
Drawing line, pressure: 0.271484375
WM_POINTERUPDATE
WM_MOUSEMOVE
Drawing line, pressure: 0.1015625
WM_POINTERUPDATE
WM_POINTERUP     <<< HERE
WM_LBUTTONUP
WM_POINTERUPDATE
WM_MOUSEMOVE
Drawing line, pressure: 0
WM_POINTERUPDATE
WM_MOUSEMOVE
Drawing line, pressure: 0
WM_POINTERUPDATE
WM_MOUSEMOVE


What I find strange is that in the end, where you (I guess) take over with mouse, you do not get WM_POINTERUPDATEs. This suggests that the EnableMouseInPointer() is not working for you. Also, all your drawing takes place after WM_MOUSEMOVE and not WM_POINTERUPDATE, for some reason...

It is no wonder the drawing continues at zero width after mouse up, since there is no code for LeftUp to stop it.

Well, my RLOGs... I just use DEBUG mode only after getting in deep trouble... Smile

Best regards,

Tom
Re: Using Pen with U++ [message #56435 is a reply to message #56434] Thu, 11 March 2021 14:54 Go to previous messageGo to next message
Tom1
Messages: 1212
Registered: March 2007
Senior Contributor
OK, here's a fix for the testing code:
#include <CtrlLib/CtrlLib.h>

using namespace Upp;

struct MyApp : TopWindow {
	Point pos;
	
	Vector<Vector<Tuple<double, Pointf>>> drawing;

	bool pendown;
	
	MyApp(){
		pendown=false;
	}
	
	virtual void LeftUp(Point p, dword)
	{
		if(IsPointerPen()) {
			DLOG("End line");
			pendown=false;
		}
		Refresh();
	}
	
	virtual void LeftDown(Point p, dword)
	{
		if(IsPointerPen()) {
			DLOG("Start line");
			pendown=true;
			drawing.Add().Add(MakeTuple(GetPenPressure(), p));
		}
		Refresh();
	}

	virtual void MouseMove(Point p, dword keyflags) {
		pos = p;
		if(IsPointerPen() && drawing.GetCount() && pendown) {
			DLOG("Drawing line, pressure: " << GetPenPressure());
			drawing.Top().Add(MakeTuple(GetPenPressure(), p));
		}
		Refresh();
	}
	
	virtual void Paint(Draw& w0)
	{
		DrawPainter w(w0, GetSize());
		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() << "Pen: " << IsPointerPen());
		Text(String() << "Pressure: " << GetPenPressure());
		Text(String() << "Rotation: " << GetPenRotation());
		Text(String() << "Tilt: " << GetPenTilt());
		Text(String() << "Barrel: " << IsPenBarrelPressed());
		Text(String() << "Inverted: " << IsPenInverted());
		Text(String() << "Eraser: " << IsPenEraserPressed()); // FIXED to IsPenEraserPressed()
		//Refresh(); // REMOVED
	}
};

GUI_APP_MAIN
{
	MyApp().Run();
}


And results for single line draw:

WM_POINTERUPDATE
WM_MOUSEMOVE
WM_POINTERUPDATE
WM_MOUSEMOVE
WM_POINTERUPDATE
WM_MOUSEMOVE
WM_POINTERDOWN
Start line
WM_POINTERUPDATE
Drawing line, pressure: 0.107421875
WM_POINTERUPDATE
Drawing line, pressure: 0.154296875
WM_POINTERUPDATE
Drawing line, pressure: 0.205078125
WM_POINTERUPDATE
Drawing line, pressure: 0.2255859375
WM_POINTERUPDATE
Drawing line, pressure: 0.2255859375
WM_POINTERUPDATE
Drawing line, pressure: 0.2255859375
WM_POINTERUPDATE
Drawing line, pressure: 0.228515625
WM_POINTERUPDATE
Drawing line, pressure: 0.2451171875
WM_POINTERUPDATE
Drawing line, pressure: 0.2451171875
WM_MOUSEMOVE
WM_LBUTTONDOWN
WM_MOUSEMOVE
WM_POINTERUPDATE
Drawing line, pressure: 0.244140625
WM_MOUSEMOVE
WM_POINTERUPDATE
Drawing line, pressure: 0.263671875
WM_MOUSEMOVE
WM_POINTERUPDATE
Drawing line, pressure: 0.2802734375
WM_MOUSEMOVE
WM_POINTERUPDATE
Drawing line, pressure: 0.29296875
WM_MOUSEMOVE
WM_POINTERUPDATE
Drawing line, pressure: 0.3056640625
WM_MOUSEMOVE
WM_POINTERUPDATE
Drawing line, pressure: 0.3193359375

...

Drawing line, pressure: 0.4169921875
WM_MOUSEMOVE
WM_POINTERUPDATE
Drawing line, pressure: 0.4052734375
WM_MOUSEMOVE
WM_POINTERUPDATE
Drawing line, pressure: 0.37890625
WM_MOUSEMOVE
WM_POINTERUPDATE
Drawing line, pressure: 0.365234375
WM_MOUSEMOVE
WM_POINTERUPDATE
Drawing line, pressure: 0.3359375
WM_MOUSEMOVE
WM_POINTERUPDATE
Drawing line, pressure: 0.0625
WM_MOUSEMOVE
WM_POINTERUP
End line
WM_LBUTTONUP
WM_POINTERUPDATE
WM_MOUSEMOVE
WM_POINTERUPDATE
WM_MOUSEMOVE
WM_POINTERUPDATE
WM_MOUSEMOVE
WM_POINTERUPDATE
WM_POINTERUPDATE
WM_MOUSEMOVE
WM_POINTERUPDATE
WM_MOUSEMOVE
WM_POINTERUPDATE
WM_MOUSEMOVE
WM_POINTERUPDATE
WM_MOUSEMOVE


Best regards,

Tom
Re: Using Pen with U++ [message #56436 is a reply to message #56435] Thu, 11 March 2021 16:26 Go to previous messageGo to next message
Tom1
Messages: 1212
Registered: March 2007
Senior Contributor
Hi,

This change fixes some tails when drawing fast. (This actually brings in your original 'ignoreclick' code and more.)

	static bool disableOldWMs=false; // When true, blocks out original WM_MOUSEMOVE, WM_LBUTTONUP, WM_LBUTTONDOWN
		
	switch(message) {
	case WM_POINTERDOWN:
	case WM_POINTERUPDATE:
	case WM_POINTERUP:
		{

			POINT p = Point((LONG)lParam);
			ScreenToClient(hwnd, &p);

			pen = false;
			pen_pressure = pen_rotation = Null;
			pen_tilt = Null;
			pen_eraser = false;
			pen_barrel = false;
			pen_inverted = false;
			
			static BOOL (WINAPI *EnableMouseInPointer)(BOOL fEnable);
			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 *GetPointerTouchInfo)(UINT32 pointerId, POINTER_TOUCH_INFO *touchInfo);

			ONCELOCK {
				DllFn(EnableMouseInPointer, "User32.dll", "EnableMouseInPointer");
				if(EnableMouseInPointer && EnableMouseInPointer(true)) disableOldWMs=true; // Switching over to WM_POINTER* functions for mouse
				
				DllFn(GetPointerType, "User32.dll", "GetPointerType");
				DllFn(GetPointerInfo, "User32.dll", "GetPointerInfo");
				DllFn(GetPointerPenInfo, "User32.dll", "GetPointerPenInfo");
				DllFn(GetPointerTouchInfo, "User32.dll", "GetPointerTouchInfo");
			};
			
			POINTER_INPUT_TYPE pointerType;
			

			UINT32 pointerId = GET_POINTERID_WPARAM(wParam);
			if(GetPointerType && GetPointerType(pointerId, &pointerType)) {
				switch(pointerType){
					case PT_PEN:{
						POINTER_PEN_INFO ppi;
						if(GetPointerPenInfo && GetPointerPenInfo(pointerId, &ppi)) {
							pen = true;
							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;
							
						}
						break;
					}
					case PT_TOUCH:{
						POINTER_TOUCH_INFO pti;
						if(GetPointerTouchInfo && GetPointerTouchInfo(pointerId, &pti)) {
							// Add something touch specific here some day maybe...
						}
						break;
					}
					default:{
						POINTER_INFO pi;
						if(GetPointerInfo && GetPointerInfo(pointerId, &pi)) {
						}
						break;
					}
				}

				switch(message){
					case WM_POINTERDOWN:
						ClickActivateWnd();
						if(ignoreclick) return 0L;
						DoMouse(LEFTDOWN, Point(p), 0);
						if(_this) PostInput();
						break;
					case WM_POINTERUP:
						if(ignoreclick) EndIgnore();
						else DoMouse(LEFTUP, Point(p), 0);
						if(_this) PostInput();
						break;
					case WM_POINTERUPDATE:
						if(ignoreclick) {
							EndIgnore();
							return 0L;
						}
						if(_this) DoMouse(MOUSEMOVE, Point(p));
						DoCursorShape();
						break;
						
				}
				return 0L;
			}
		}
		break;
	case WM_POINTERLEAVE:
		pen = false;
		break;



The 'if(disableOldWMs) break;' are still needed in WM_MOUSEMOVE, WM_LBUTTONUP, WM_LBUTTONDOWN.

Does this work for you?

Best regards,

Tom

[Updated on: Thu, 11 March 2021 16:41]

Report message to a moderator

Re: Using Pen with U++ [message #56438 is a reply to message #56436] Fri, 12 March 2021 09:37 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 13975
Registered: November 2005
Ultimate Member
It seems to work, however I feel pretty uneasy that it is handling just LBUTTON messages and leaves the rest to "old" WMs. What about right button and double-clicks? Documentation is pretty sparse there....

If I understand you right, buttons are not a problem with Wacom, just mousemove messages. Maybe we could be more conservative, leave old messages, issue WM_MOUSEMOVE on POINTERUPDATE and solve the problem by ignoring duplicit messages (store screen hwnd and position, only issue mousemove if it changes...)?

Mirek
Re: Using Pen with U++ [message #56439 is a reply to message #56438] Fri, 12 March 2021 09:52 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 13975
Registered: November 2005
Ultimate Member
Or, maybe, just forget about MouseMove and add a new virtual method? E.g.

virtual Pen(Point pos, double pressure, double rotation, Pointf tilt, dword flags);

which would simply be updated on WM_POINTERUPDATE....
Re: Using Pen with U++ [message #56440 is a reply to message #56439] Fri, 12 March 2021 10:18 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 13975
Registered: November 2005
Ultimate Member
BTW, what do you get with

DDUMPHEX(GetMessageExtraInfo());

It looks like that 0xff515704 indicates pen for "old" WM messages, which could be useful in some context...

https://stackoverflow.com/questions/29857587/detect-if-wm-mo usemove-is-caused-by-touch-pen

Mirek
Re: Using Pen with U++ [message #56441 is a reply to message #56438] Fri, 12 March 2021 10:26 Go to previous messageGo to next message
Tom1
Messages: 1212
Registered: March 2007
Senior Contributor
Hi,

WM_LBUTTONDOWN comes in late with Wacom, so it needs to be caught with WM_POINTERDOWN. WM_MOUSEMOVEs are also missing in the beginning of draw, so WM_POINTERUPDATE needs to replace WM_MOUSEMOVE there.

The only way (I can see) to properly handle each pointing device when more than one exist, is taking the full control of moves and left button to WM_POINTER* messages.

I think that we should aim for the Pen to work in place of a mouse as logically and cleanly as possible without any changes to the final application. I'm thinking of people using pen with U++ applications without specific pen support. Their experience should not suffer.

Only when pressure/tilt/rotation are beneficial for the application, then additional calls should be placed to acquire their values.

If I understand it correctly, the RBUTTON and DOUBLECLICKS are not part of WM_POINTER* message family. Anyway, at least RBUTTON works through the old messages. I have not tried doubleclicking yet... I'll do it after I get back to my tablet later in the afternoon.

Best regards,

Tom
Re: Using Pen with U++ [message #56442 is a reply to message #56440] Fri, 12 March 2021 10:28 Go to previous messageGo to next message
Tom1
Messages: 1212
Registered: March 2007
Senior Contributor
mirek wrote on Fri, 12 March 2021 11:18
BTW, what do you get with

DDUMPHEX(GetMessageExtraInfo());

It looks like that 0xff515704 indicates pen for "old" WM messages, which could be useful in some context...

https://stackoverflow.com/questions/29857587/detect-if-wm-mo usemove-is-caused-by-touch-pen

Mirek


I'll need to check this when I get to my tablet...

You're moving fast! Just cannot keep up writing my replies... Smile

Best regards,

Tom
Re: Using Pen with U++ [message #56443 is a reply to message #56442] Fri, 12 March 2021 11:56 Go to previous messageGo to next message
Tom1
Messages: 1212
Registered: March 2007
Senior Contributor
Tom1 wrote on Fri, 12 March 2021 11:28
mirek wrote on Fri, 12 March 2021 11:18
BTW, what do you get with

DDUMPHEX(GetMessageExtraInfo());

It looks like that 0xff515704 indicates pen for "old" WM messages, which could be useful in some context...

https://stackoverflow.com/questions/29857587/detect-if-wm-mo usemove-is-caused-by-touch-pen

Mirek


I'll need to check this when I get to my tablet...

You're moving fast! Just cannot keep up writing my replies... Smile

Best regards,

Tom


It's
GetMessageExtraInfo() = 0x0
all the way for WM_POINTER*, WM_MOUSEMOVE, WM_LBUTTONUP, WM_LBUTTONDOWN...

Best regards,

Tom
Re: Using Pen with U++ [message #56444 is a reply to message #56443] Fri, 12 March 2021 12:35 Go to previous messageGo to next message
Tom1
Messages: 1212
Registered: March 2007
Senior Contributor
Hi,

It seems, when the pen is moving fast, Windows filters out part of the intermediate pen positions. Therefore, processing GetPointerPenInfoHistory() improves drawing quality especially at higher pen speeds:

	static bool disableOldWMs=false; // When true, blocks out original WM_MOUSEMOVE, WM_LBUTTONUP, WM_LBUTTONDOWN
		
	switch(message) {
	case WM_POINTERDOWN:
	case WM_POINTERUPDATE:
	case WM_POINTERUP:
		{

			POINT p = Point((LONG)lParam);
			ScreenToClient(hwnd, &p);

			pen = false;
			pen_pressure = pen_rotation = Null;
			pen_tilt = Null;
			pen_eraser = false;
			pen_barrel = false;
			pen_inverted = false;
			
			static BOOL (WINAPI *EnableMouseInPointer)(BOOL fEnable);
			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 *GetPointerTouchInfo)(UINT32 pointerId, POINTER_TOUCH_INFO *touchInfo);
			static BOOL (WINAPI *GetPointerPenInfoHistory)(UINT32 pointerId, UINT32 *entriesCount, POINTER_PEN_INFO *penInfo);

			ONCELOCK {
				DllFn(EnableMouseInPointer, "User32.dll", "EnableMouseInPointer");
				if(EnableMouseInPointer && EnableMouseInPointer(true)) disableOldWMs=true; // Switching over to WM_POINTER* functions for mouse
				
				DllFn(GetPointerType, "User32.dll", "GetPointerType");
				DllFn(GetPointerInfo, "User32.dll", "GetPointerInfo");
				DllFn(GetPointerPenInfo, "User32.dll", "GetPointerPenInfo");
				DllFn(GetPointerTouchInfo, "User32.dll", "GetPointerTouchInfo");

				DllFn(GetPointerPenInfoHistory, "User32.dll", "GetPointerPenInfoHistory");
			};
			
			POINTER_INPUT_TYPE pointerType;
			

			UINT32 pointerId = GET_POINTERID_WPARAM(wParam);
			if(GetPointerType && GetPointerType(pointerId, &pointerType)) {
				switch(pointerType){
					case PT_PEN:{
						
						UINT32 hc=256;
						POINTER_PEN_INFO ppit[hc];
						if(message==WM_POINTERUPDATE && GetPointerPenInfoHistory && GetPointerPenInfoHistory(pointerId, &hc, ppit)) {
							for(int i=hc-1;i>=0;i--){
								pen = true;
								if(ppit[i].penFlags & PEN_FLAG_BARREL)
									pen_barrel = true;
								if(ppit[i].penFlags & PEN_FLAG_INVERTED)
									pen_inverted = true;
								if(ppit[i].penFlags & PEN_FLAG_ERASER)
									pen_eraser = true;
								if(ppit[i].penMask & PEN_MASK_PRESSURE)
									pen_pressure = ppit[i].pressure / 1024.0;
								if(ppit[i].penMask & PEN_MASK_ROTATION)
									pen_rotation = ppit[i].rotation * M_2PI / 360;
								if(ppit[i].penMask & PEN_MASK_TILT_X)
									pen_tilt.x = ppit[i].tiltX * M_2PI / 360;
								if(ppit[i].penMask & PEN_MASK_TILT_Y)
									pen_tilt.y = ppit[i].tiltY * M_2PI / 360;
								
								POINT hp = ppit[i].pointerInfo.ptPixelLocation;
								ScreenToClient(hwnd, &hp);
	
								if(ignoreclick) {
									EndIgnore();
									return 0L;
								}
								if(_this) DoMouse(MOUSEMOVE, Point(hp));
								DoCursorShape();
								
							}
							return 0L;
						}
	
						POINTER_PEN_INFO ppi;
						if(GetPointerPenInfo && GetPointerPenInfo(pointerId, &ppi)) {
							if(ppi.pointerInfo.historyCount){
							}
								
							pen = true;
							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;
						}
						break;
					}
					case PT_TOUCH:{
						POINTER_TOUCH_INFO pti;
						if(GetPointerTouchInfo && GetPointerTouchInfo(pointerId, &pti)) {
							// Add something touch specific here some day maybe...
						}
						break;
					}
/*					default:{
						POINTER_INFO pi;
						if(GetPointerInfo && GetPointerInfo(pointerId, &pi)) {
						}
						break;
					}
*/				}

				switch(message){
					case WM_POINTERDOWN:
						ClickActivateWnd();
						if(ignoreclick) return 0L;
						DoMouse(LEFTDOWN, Point(p), 0);
						if(_this) PostInput();
						break;
					case WM_POINTERUP:
						if(ignoreclick) EndIgnore();
						else DoMouse(LEFTUP, Point(p), 0);
						if(_this) PostInput();
						break;
					case WM_POINTERUPDATE:
						if(ignoreclick) {
							EndIgnore();
							return 0L;
						}
						if(_this) DoMouse(MOUSEMOVE, Point(p));
						DoCursorShape();
						break;
						
				}
				return 0L;
			}
		}
		break;
	case WM_POINTERLEAVE:
		pen = false;
		break;
...


Best regards,

Tom
Re: Using Pen with U++ [message #56446 is a reply to message #56444] Fri, 12 March 2021 17:50 Go to previous messageGo to next message
Tom1
Messages: 1212
Registered: March 2007
Senior Contributor
OK, now I checked LeftDouble(), RightDouble(), RightUp()... and NONE of them works with the above code.

Need to think more...

Best regards,

Tom

EDIT: I'm starting to believe that if WM_POINTER* is used for mouse, it needs processing WM_POINTERUP and WM_POINTERDOWN in a way that checks IS_POINTER_FIRSTBUTTON_WPARAM(wParam), IS_POINTER_SECONDBUTTON_WPARAM(wParam) and so on to detect WM_LBUTTONUP/DOWN and WM_RBUTTONUP/DOWN and others correctly. Seems a bit complex to me. And still DOUBLECLICKs are a mystery.

[Updated on: Fri, 12 March 2021 18:05]

Report message to a moderator

Re: Using Pen with U++ [message #56447 is a reply to message #56446] Fri, 12 March 2021 18:32 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 13975
Registered: November 2005
Ultimate Member
Well, that is about what I expected.

The Pen virtual method seems more and more favorable solution.

Can you please test DDUMPHEX(GetMessageExtraInfo()); ? It would be really helpful in new API, which would use normal mouse, but put K_PEN into flags of Mouse messages... (because we WILL need to distinguish these).

Mirek
Re: Using Pen with U++ [message #56448 is a reply to message #56447] Fri, 12 March 2021 19:04 Go to previous messageGo to next message
Tom1
Messages: 1212
Registered: March 2007
Senior Contributor
Hi,

GetMessageExtraInfo() returned always zero... Sad

(Reported this earlier.)

Best regards,

Tom
Re: Using Pen with U++ [message #56449 is a reply to message #56448] Fri, 12 March 2021 20:27 Go to previous messageGo to next message
Tom1
Messages: 1212
Registered: March 2007
Senior Contributor
Mirek,

Can you test this:

	switch(message) {
	case WM_POINTERDOWN:
	case WM_POINTERUPDATE:
	case WM_POINTERUP:
		{

			POINT p = Point((LONG)lParam);
			ScreenToClient(hwnd, &p);

			pen = false;
			pen_pressure = pen_rotation = Null;
			pen_tilt = Null;
			pen_eraser = false;
			pen_barrel = false;
			pen_inverted = false;
			
			static BOOL (WINAPI *EnableMouseInPointer)(BOOL fEnable);
			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 *GetPointerTouchInfo)(UINT32 pointerId, POINTER_TOUCH_INFO *touchInfo);
			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(GetPointerTouchInfo, "User32.dll", "GetPointerTouchInfo");

				DllFn(GetPointerPenInfoHistory, "User32.dll", "GetPointerPenInfoHistory");
			};
			
			POINTER_INPUT_TYPE pointerType;
			

			UINT32 pointerId = GET_POINTERID_WPARAM(wParam);
			if(GetPointerType && GetPointerType(pointerId, &pointerType)) {
				switch(pointerType){
					case PT_PEN:{
						
						UINT32 hc=256;
						POINTER_PEN_INFO ppit[hc];
						if(message==WM_POINTERUPDATE && GetPointerPenInfoHistory && GetPointerPenInfoHistory(pointerId, &hc, ppit)) {
							for(int i=hc-1;i>=0;i--){
								pen = true;
								if(ppit[i].penFlags & PEN_FLAG_BARREL)
									pen_barrel = true;
								if(ppit[i].penFlags & PEN_FLAG_INVERTED)
									pen_inverted = true;
								if(ppit[i].penFlags & PEN_FLAG_ERASER)
									pen_eraser = true;
								if(ppit[i].penMask & PEN_MASK_PRESSURE)
									pen_pressure = ppit[i].pressure / 1024.0;
								if(ppit[i].penMask & PEN_MASK_ROTATION)
									pen_rotation = ppit[i].rotation * M_2PI / 360;
								if(ppit[i].penMask & PEN_MASK_TILT_X)
									pen_tilt.x = ppit[i].tiltX * M_2PI / 360;
								if(ppit[i].penMask & PEN_MASK_TILT_Y)
									pen_tilt.y = ppit[i].tiltY * M_2PI / 360;
								
								POINT hp = ppit[i].pointerInfo.ptPixelLocation;
								ScreenToClient(hwnd, &hp);
	
								if(ignoreclick) {
									EndIgnore();
									return 0L;
								}
								if(_this) DoMouse(MOUSEMOVE, Point(hp));
								DoCursorShape();
								
							}
							return 0L;
						}
	
						POINTER_PEN_INFO ppi;
						if(GetPointerPenInfo && GetPointerPenInfo(pointerId, &ppi)) {
							pen = true;
							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;
						}
						break;
					}
					case PT_TOUCH:{
						POINTER_TOUCH_INFO pti;
						if(GetPointerTouchInfo && GetPointerTouchInfo(pointerId, &pti)) {
							// Add something touch specific here some day maybe...
						}
						break;
					}
				}

				switch(message){
					case WM_POINTERDOWN:
						ClickActivateWnd();
						if(ignoreclick) return 0L;
						DoMouse(LEFTDOWN, Point(p), 0);
						if(_this) PostInput();
						break;
					case WM_POINTERUP:
						if(ignoreclick) EndIgnore();
						else DoMouse(LEFTUP, Point(p), 0);
						if(_this) PostInput();
						break;
					case WM_POINTERUPDATE:
						if(ignoreclick) {
							EndIgnore();
							return 0L;
						}
						if(_this) DoMouse(MOUSEMOVE, Point(p));
						DoCursorShape();
						break;
						
				}
				return 0L;
			}
		}
		break;
	case WM_POINTERLEAVE:
		pen = false;
		break;


No blocking of original WM_MOUSEMOVE, etc. required at all.

For some reason, with this code I do not get those WM_MOUSEMOVE messages for Pen, but only for mouse. Similarly, WM_POINTER... messages only appear for Pen.

Right clicks and double clicks work for mouse as before. So this is closest to a working solution so far.

Best regards,

Tom
Re: Using Pen with U++ [message #56452 is a reply to message #56449] Sat, 13 March 2021 12:42 Go to previous messageGo to next message
Tom1
Messages: 1212
Registered: March 2007
Senior Contributor
Hi,

OK, now I found the reason why the original code produced both WM_MOUSEMOVEs and WM_POINTERUPDATEs for the pen moving: When case WM_POINTERUPDATE: exits with break; , it causes some emulation to result in WM_MOUSEMOVE. However, when WM_POINTERUPDATE exits with return 0L; , there will not be any WM_MOUSEMOVE and the two get processed separately and correctly.

This must be the reason why the latest code works.

Best regards,

Tom
Re: Using Pen with U++ [message #56453 is a reply to message #56449] Sat, 13 March 2021 14:19 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 13975
Registered: November 2005
Ultimate Member
Looks good, however, should you return immediately after processing the history?
Re: Using Pen with U++ [message #56454 is a reply to message #56453] Sat, 13 March 2021 14:39 Go to previous messageGo to next message
Tom1
Messages: 1212
Registered: March 2007
Senior Contributor
mirek wrote on Sat, 13 March 2021 15:19
Looks good, however, should you return immediately after processing the history?


I think so, yes. History[0] contains the latest POINTERUPDATE, so everything gets processed this way.

Best regards,

Tom
Re: Using Pen with U++ [message #56456 is a reply to message #56454] Sat, 13 March 2021 15:07 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 13975
Registered: November 2005
Ultimate Member
OK, done some cleanup/deduplication, I think this might be final. Can you test?

And now important question: Does Wacom work with Linux? Smile

Mirek
Re: Using Pen with U++ [message #56457 is a reply to message #56454] Sat, 13 March 2021 15:10 Go to previous messageGo to next message
Tom1
Messages: 1212
Registered: March 2007
Senior Contributor
... I'm just thinking about the situation, where an application written with U++ has not been specifically designed to support pen: I think that the barrel button should be mapped to the right mouse button in U++ -- as is the default Windows pen behavior, I think. This (and maybe some other things) should give a reasonable pen experience without any special work on the application itself.

The default pen behavior can be seen in:

https://docs.microsoft.com/en-us/previous-versions/windows/d esktop/inputmsg/wm-pointerdown

Look specifically at IS_POINTER_FIRSTBUTTON_WPARAM(wParam) and IS_POINTER_SECONDBUTTON_WPARAM(wParam)...

Best regards,

Tom

Re: Using Pen with U++ [message #56458 is a reply to message #56456] Sat, 13 March 2021 15:20 Go to previous messageGo to previous message
Tom1
Messages: 1212
Registered: March 2007
Senior Contributor
mirek wrote on Sat, 13 March 2021 16:07
OK, done some cleanup/deduplication, I think this might be final. Can you test?

And now important question: Does Wacom work with Linux? Smile

Mirek


Yes, it works just great! Nice cleanup too.

You can remove this too:

static BOOL (WINAPI *EnableMouseInPointer)(BOOL fEnable);


Tracking pen_history is a mystery to me, though... Any reason for that?

Currently my linux is on the virtual machine on top of windows... It does not see pen operations directly. I need to check if I can reconnect the wacom directly to the VM...

Best regards,

Tom

EDIT: A quick search says it should work after installing some X wacom drivers...

[Updated on: Sat, 13 March 2021 15:23]

Report message to a moderator

Previous Topic: WString vs Grapheme Cluster idea (with possible flaw)
Next Topic: .gitignore
Goto Forum:
  


Current Time: Sat Apr 27 18:52:57 CEST 2024

Total time taken to generate the page: 0.03827 seconds