似乎StikyNot.exe下的所有笔记都是单个exes而不是多个。这也就是说它的位置坐标总是0,0,0,0。有没有办法移动它?我尝试使用Win32的MoveWindow功能但没有成功。
答案 0 :(得分:1)
这是一个如何遍历所有Sticky Note窗口并移动每个窗口的示例。 (为简洁起见,已删除错误检查。另外,请务必阅读最后的注释,以获得有关此实现的一些注释。)
首先,我们必须定义RECT
结构。
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
public RECT(int l, int t, int r, int b)
{
Left = l;
Top = t;
Right = r;
Bottom = b;
}
public int Left;
public int Top;
public int Right;
public int Bottom;
}
然后是一些关键的p / Invokes。我们需要FindWindowExW
来找到具有正确窗口类的窗口以获得便利贴。我们还需要GetWindowRect
,所以我们可以计算窗口的大小,所以我们只移动它,而不是移动和调整大小。最后,我们需要SetWindowPos
这是非常不言自明的。
[DllImport("User32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern IntPtr FindWindowExW(IntPtr hWndParent, IntPtr hWndAfter,
string lpszClass, string lpszWindow);
[DllImport("User32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetWindowRect(IntPtr hWnd, out RECT rect);
[DllImport("User32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X,
int Y, int cx, int cy, uint uFlags);
最后我们的算法。
IntPtr hWnd = FindWindowExW(IntPtr.Zero, IntPtr.Zero, "Sticky_Notes_Note_Window", null);
if (hWnd == IntPtr.Zero)
{
int error = Marshal.GetLastWin32Error();
if (error > 0) throw new Win32Exception(error);
else return;
}
IntPtr first = hWnd;
int currentX = 0;
while (hWnd != IntPtr.Zero)
{
RECT r;
bool result = GetWindowRect(hWnd, out r);
if (!result)
{
int error = Marshal.GetLastWin32Error();
if (error > 0) throw new Win32Exception(error);
else return;
}
result = SetWindowPos(hWnd,
IntPtr.Zero,
currentX,
0,
r.Right - r.Left,
r.Bottom - r.Top,
0);
if (!result)
{
int error = Marshal.GetLastWin32Error();
if (error > 0) throw new Win32Exception(error);
else return;
}
currentX += r.Right - r.Left;
hWnd = FindWindowExW(IntPtr.Zero, hWnd, "Sticky_Notes_Note_Window", null);
if (hWnd == IntPtr.Zero)
{
int error = Marshal.GetLastWin32Error();
if (error > 0) throw new Win32Exception(error);
else return;
}
if (hWnd == first) hWnd = IntPtr.Zero;
}
它是如何工作的?首先,使用像Spy ++这样的工具,我找到了窗口类。在窗口的属性表中,我们可以看到窗口的类名是Sticky_Notes_Note_Window
。
使用Spy ++中的信息,第一个窗口句柄是使用FindWindowExW
获得的。缓存此值,以便在我们完成迭代所有窗口时确定。在循环内部,我们移动窗口,然后使用FindWindowEx
再次找到具有相同类的下一个窗口,如果找不到,hWnd
将IntPtr.Zero
又称NULL
。我们还必须检查我们是否回到了迭代的开始。 (如果音符比屏幕宽,它们会向右溢出。将音符包装到另一行留作练习)
这个实现的问题是,如果第一个粘滞便笺被关闭,在我们遍历所有粘滞便笺之前,那么程序将永远不会终止。最好跟踪已经看到的所有窗口,如果再看到任何窗口,那么所有窗口都已被枚举。
另一种方法是使用EnumWindows
并在回调电话GetClassName
内查看它是否为Sticky_Notes_Note_Window
,然后采取适当行动。上面的方法需要的工作量较少,所以我选择的方法就是这样。
参考文献:
编辑:根据@ DavidHeffernan的评论添加了错误检查。还添加了关于我如何找到Window类名称的说明。