Prevent rendering of the desktop selection rectangle - c#

I'm working on small program that basically animates the wallpaper using OpenGL.
The wallpaper is all interactive(I use a global mouse hook for the mouse events), but to make it perfect when I hold down the left mouse button, I'd like the selection rectangle to not appear at all.
All I could change was disable the translucent selection rectangle using a registry key and a P/Invoke function to force the desktop to reload it's registry settings, resulting in this:
On the image you can see the selection outline which would be great if wasn't rendered when I hold and drag.
Is it possible to achieve using C#?
EDIT:
There is a partial solution to this problem that #Jonathan Potter provided:
W32.EnumChildWindows(W32.GetDesktopWindow(), (hwnd, param) =>
{
var WM_CANCELMODE = 0x001F;
var sb = new StringBuilder(256);
if (W32.GetClassName(hwnd, sb, 256) > 0)
{
if (sb.ToString() == "SysListView32")
W32.SendMessage(hwnd, WM_CANCELMODE, 0, IntPtr.Zero);
}
return true;
}, IntPtr.Zero);
The problem with this solution is that now whenever I try selecting anything on the desktop, it won't, since I am literally cancelling the selection just as I begin holding the mouse button.

Related

Winrt - Adjusting flyout according to where it appears

I have a GridView in a windows store project, that contains some big squares, and inside those i have a list of user images, when i tap on of those images a flyout appears on the right showing some information like this.
the problem is that my gridview extends to the edges of the screen and beyond, and when that does i get this situation, i press the user with the red border near the edge of the screen and flyout appears on left.
My flyout placement is set to Right, and im guessing since the element i press is near the edge it follows the Fall back order with according to this is Right > Left > Top > Bottom.
What i would like to know is how to detect this happens, so i can adjust my flyout position, or another viable alternative :)
After searching through properties and Dependency properties on Flyout and FlyoutBase, I haven't found a way to simply get the actual placement of the Flyout (which is unfortunate because I think that can be important, as we see in your case). Perhaps you can try what was proposed here by implementing a method that compares the desired size of the Flyout with the available space.
You can subscribe to FlyOut.Opened event and compare absolute coordinates of the flyout and the element you're showing it at. Here is an example for top/bottom flyout placement (easily extendable to check for left/right as well):
private void FlyOut_Opened(object sender, object e)
{
GeneralTransform flyOutTransform =
flyOut.Content.TransformToVisual(Window.Current.Content);
Point flyOutPosition =
flyOut.TransformPoint(new Point(0, 0));
GeneralTransform showAtElementTransform =
showAtElementTransform.TransformToVisual(Window.Current.Content);
Point showAtElementPosition =
showAtElementPosition.TransformPoint(new Point(0, 0));
if(flyOutPosition.Y < showAtElementPosition.Y)
{
// top
}
else
{
// bottom
}
}

Programmatically Maximize Window On Half Of Screen

I want to maximize a random window on the left side of my screen. Can I use Windows Aero functions from my code ? This window can be maximized like that with the mouse. I just want to do that programmatically.
I use C# and I can get the IntPtr of the window.
If possible without faking mouse or keyboard input.
This can be done without p/invoke.
Try this:
Rectangle rect = Screen.PrimaryScreen.WorkingArea;
rect.Width = rect.Width / 2;
Bounds = rect;
This will put the current window on the left of the primary screen.
Then just add this to put it on the right of the screen.
Location = new Point(rect.Width, 0);
It's not exactly the same but fakes it well:
ShowWindow(handle, SW_MAXIMIZE);
// for a split second you might see a maximized window here
MoveWindow(handle, 0, 0, Screen.PrimaryScreen.WorkingArea.Width / 2, Screen.PrimaryScreen.WorkingArea.Height, true);
Will require heavy lifting for real-time placements, especially for non-child processes. Example - www.ishadow.com/vdm. For manual "fixing" of maximized windows position MoveWindow(hWnd, startPos, 0, winWidth, winHeight, true) after ShowWindow(hWnd, SW_MAXIMIZE) usually (try Task Manager on Windows 10) works as pointed above.

Simulate Mouse Drag Programmatically

I have a Windows Forms application with a control. The control consists of a chart panel with a canvas on which I paint. What I would like to do is to programmatically mouse drag the panel so that I have a specific distance between the right edge of the canvas and the last item painted on the canvas. I have tried two approaches. The both work in the sense that the panel is dragged as desired BUT I cannot seem to be able to get the precision of movement I desire. I coded a mouse simulator and have tried two approaches.
Approach 1:
if(this.ChartControl.ChartPanel.CanFocus)
{
// ... Focus the chart panel to be adjusted.
this.ChartControl.ChartPanel.Focus();
// ... Move cursor to lastBarScreenCoordinates on the chart panel to be adjusted.
Cursor.Position = new Point(lastBarScreenCoordinates.X, lastBarScreenCoordinates.Y);
MouseSimulator.SetMouseDragThresholds();
// ... Move chart panel to required position.
MouseSimulator.LeftMouseButtonDown(lastBarScreenCoordinates.X, lastBarScreenCoordinates.Y);
MouseSimulator.MouseMove(lastBarScreenCoordinates.X-positionShift,
lastBarScreenCoordinates.Y);
MouseSimulator.LeftMouseButtonUp(lastBarScreenCoordinates.X-positionShift,
lastBarScreenCoordinates.Y);
MouseSimulator.ResetMouseDragThresholds(_cx_default, _cy_default);
// ... Redraw the chart panel.
this.ChartControl.ChartPanel.Refresh();
// ... Reset cursor to its starting position.
Cursor.Position = new Point(startingCursorX, startingCursorY);
}
Approach 2:
if(this.ChartControl.ChartPanel.CanFocus)
{
// ... Focus the chart panel to be adjusted.
this.ChartControl.ChartPanel.Focus();
// ... Move cursor to lastBarScreenCoordinates on the chart panel to be adjusted.
Cursor.Position = new Point(lastBarScreenCoordinates.X, lastBarScreenCoordinates.Y);
MouseSimulator.SetMouseDragThresholds();
// ... Move chart panel to required position.
MouseSimulator.LeftMouseButtonDown(lastBarScreenCoordinates.X, lastBarScreenCoordinates.Y);
Cursor.Position = new Point(lastBarScreenCoordinates.X-positionShift,
lastBarScreenCoordinates.Y);
WindowsCommunication.SendMessage(this.ChartControl.Handle, 0x200, IntPtr.Zero,IntPtr.Zero);
MouseSimulator.LeftMouseButtonUp(lastBarScreenCoordinates.X-positionShift,
lastBarScreenCoordinates.Y);
MouseSimulator.ResetMouseDragThresholds(_cx_default, _cy_default);
// ... Redraw the chart panel.
this.ChartControl.ChartPanel.Refresh();
// ... Reset cursor to its starting position.
Cursor.Position = new Point(startingCursorX, startingCursorY);
}
I am using SendInput for simulating mouse clicks. Here is sample left mouse button down code ...
public static void LeftMouseButtonDown(int x, int y)
{
INPUT mouseInput = new INPUT();
mouseInput.type = SendInputEventType.InputMouse;
mouseInput.mkhi.mi.dx = CalculateAbsoluteCoordinateX(x);
mouseInput.mkhi.mi.dy = CalculateAbsoluteCoordinateY(y);
mouseInput.mkhi.mi.mouseData = 0;
mouseInput.mkhi.mi.time = 0;
mouseInput.mkhi.mi.dwFlags = MouseEventFlags.MOUSEEVENTF_LEFTDOWN;
SendInput(1, ref mouseInput, Marshal.SizeOf(new INPUT()));
}
And I calculate normalized absolute coordinates for the mouse as follows ...
private static int CalculateAbsoluteCoordinateX(int x)
{
return ((x * 65536) + GetSystemMetrics(SystemMetric.SM_CXSCREEN) - 1) /
GetSystemMetrics(SystemMetric.SM_CXSCREEN);
}
So here are the precision issues. If I use Approach 1 (mouse move), the measured distance between the last item painted and the right edge of the canvas is different from what I set in positionShift and the cursor position difference does not equal positionShift. I initially thought it was due to pointer ballistics issues so I tried using Approach 2. Approach 2 does give me precision in pointer positioning but I am still having difficulty in that the panel moves but the distance between the last bar painted and the right edge of the canvas does not equal the positionShift amount as it should. It always seems to be off. I have been working on this for a long time now and am at my wits end. I am not sure what is going on here. How to improve the precision in my canvas drag by simulated mouse drag?
Well what you can do is this, First of all I believe the SendInput API allows for an AbsoluteValue flag so there is no need to calculate those values which may be the issue but most likely not.
Although I am curious as to why you are using a Mouse Drag opperation for this. It seems like all you want to do is reposition the canvas on every draw by some specified amount. if this is the case why not just set it explicitly on the canvas itself. Also it is unclear if you are using pure WinForms or WPF. The unclear bit being Canvas which I am fairly certain is only usable with WPF enabled windows.
That being said
WPF fix,
Depending on the Object containing the canvas just set its margin appropriately for the situation, since I do not know the data you are working with I cant say much about that. But this is a relatively simple idea so let me know if that works, it should give you, at least close too, a pixel perfect alignment.
WinForms,
Just do the above for the "Canvas" object you were talking about, or use absolute coordinates of the object to move it around.
If you could supply a sample of what you were working on looked like roughly maybe we could have a better idea of what you mean.

How can I resize the windows work area, and then update the other windows to reflect the change please?

I have a toolbar application which changes the work area of the desktop and positions itself in the gap (either at the top or bottom of the screen). I need a function which will resize the other windows so that they are not left behind the toolbar after the resizing (the toolbar is always on top). I'm using the function below to change the work area:
private bool SetWorkspace(RECT rect)
{
bool result = SystemParametersInfo(SPI_SETWORKAREA,
0,
ref rect,
SPIF_change);
if (!result)
{
MessageBox.Show("The last error was: " +
Marshal.GetLastWin32Error().ToString());
}
this.minAll();
return result;
}
and the minAll() function is how I'm resizing the other windows:
public void minAll(){
IntPtr lHwnd = FindWindow("Shell_TrayWnd", null);
SendMessage(lHwnd, WM_COMMAND, (IntPtr)MIN_ALL, IntPtr.Zero);
System.Threading.Thread.Sleep(10);
SendMessage(lHwnd, WM_COMMAND, (IntPtr)MIN_ALL_UNDO, IntPtr.Zero);
System.Threading.Thread.Sleep(10);
}
This method works, in that the workarea does get resized and no window keeps its old position outside it, but there are a few problems:
Normal (ie. not maximised or minimized) windows are sometimes made so
small that they aren't displayed, and have to be maximised from the
taskbar (Vista) to be visible
Sometimes the method makes other
windows 'always on top' when they shouldn't be
It changes the z-order of the windows, seemingly at random
The first two of these problems are fixed if you close and reopen the affected windows, but it's hardly an ideal solution and I can't even manually correct the z-order (I tried saving the z-order before the method and then restoring it afterwards, but no luck).
So, can anyone see what's wrong with how I'm doing this, or does anyone know how it's supposed to be done please?
The correct way to do this is to create an AppBar. See SHAppBarMessage. There is a C++ sample in the Knowledge Base. There is a C# sample on CodeProject.

Custom form designer, move/resize controls using WinAPI

I have to fix some problems and enchance form designer written long ago for a database project.
In Design Panel class code I encountered these lines
private void DesignPanel_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
(sender as Control).Capture = false;
switch (FMousePosition)
{
case MousePosition.mpNone:
SendMessage((sender as Control).Handle, WM_SYSCOMMAND, 0xF009, 0);
break;// Move
case MousePosition.mpRightBottom:
SendMessage((sender as Control).Handle, WM_SYSCOMMAND, 0xF008, 0);
break;//RB
case MousePosition.mpLeftBottom:
SendMessage((sender as Control).Handle, WM_SYSCOMMAND, 0xF007, 0);
// ... here are similar cases ...
case MousePosition.mpLeft:
SendMessage((sender as Control).Handle, WM_SYSCOMMAND, 0xF001, 0);
break;//L
}
}
}
FMousePosition indicates whether mouse was over any edge of selected control.
What confusing me is these windows messages: it seems there is no documentation on WM_SYSCOMMAND with parameters 0xF001-0xF009 (maybe it starts some kind of 'drag/resize sequence'). Any ideas?
If my suggestion is right, then how can I cancel these sequences?
They are undocumented parameters. After searching I managed to find this list.
0xF000 (SC_SIZE, Center cursor on the form)
0xF001 (SC_SZLEFT, Resize from left)
0xF002 (SC_SZRIGHT, Resize from right)
0xF003 (SC_SZTOP, Resize from top)
0xF004 (SC_SZTOPLEFT, Lock the bottom right corner of the form, the top left corner move for resize)
0xF005 (SC_SZTOPRIGHT, Same from bottom left corner)
0xF006 (SC_SZBOTTOM, Lock top right and left border, resize bottom)
0xF007 (SC_SZBOTTOMLEFT, Lock top and right border, resize other border)
0xF008 (SC_SZBOTTOMRIGHT, Lock left and top border and resize other)
0xF009 (SC_SIZE|0x9, Drag from anywhere)
0xF00F (SC_SEPARATOR)
0xF010 (SC_MOVE, Put cursor centered at the upper order)
0xF012 (SC_DRAGMOVE, move by dragging)
0xF020 (SC_MINIMIZE, Auto-Minimize Form)
0xF030 (SC_MAXIMIZE, Auto-Maximize Form)
0xF040 (SC_NEXTWINDOW, Stop! You don't want that, it will lock all mouse click and make you reboot)
0xF148 (SC_SCREENSAVE|0x8, Activate ScreenSaver)
0xF13E (SC_TASKLIST|0xE, Activate StartButton)
Reference: http://www.delphi3000.com/articles/article_1054.asp#Comments
Based on my Win32 Programming (Rector and Newcomer) p902-903 explains WM_SYSCOMMAND is sent when the user selects an item from the system menu (rather than sending the normal WM_COMMAND).
The MSDN help says SC_SIZE = 0xF000 and it and Win32 Programming also say Windows uses the four low-order bits of the predefined system menu IDs internally but doesn't go on to clarify their use. Thanks stukelly for clarifying them.

Categories