c# 移动 Winamp 主窗口

标签 c# winapi resize winamp

我正在尝试使用以下代码移动 winamps 主窗口:

[DllImport("user32.dll")]
    static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint);
[DllImport("user32.dll")]
    static extern bool GetWindowRect(IntPtr hWnd, out RECT rect);
[DllImport("user32.dll")]
    static extern IntPtr GetForegroundWindow();

static void resize()
{
   Process w = new Process();
   w.StartInfo = new ProcessStartInfo("winamp.exe");
   w.Start();
   Thread.Sleep(5000);
   IntPtr hWnd = GetForegroundWindow();
   RECT rect;
   GetWindowRect(hWnd, out rect);
   int width = rect.right - rect.left;
   int height = rect.bottom - rect.top;
   MoveWindow(hWnd, 0, 0, width, height, true);
}

此代码片段适用于我测试的所有进程,Winamp 除外。当我使用进程的 mainWindowHandle 时,它会移动另一个窗口。 有人知道如何让它与 Winamp 一起工作吗?

最佳答案

通过以下代码,我可以确认更改 WinAmp 的主窗口大小无法通过 Win32 API 进行。

通过 Win32 API 更改其他 winamp 窗口大小确实有效,但这不是解决方案:

public partial class Form1 : Form
{    
[DllImport("user32")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool EnumChildWindows(IntPtr window, EnumWindowProc callback, IntPtr i);
[DllImport("user32.dll")]
static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint);
[DllImport("user32.dll")]
static extern bool GetWindowRect(IntPtr hWnd, out RECT rect);    
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
    public int Left;        // x position of upper-left corner
    public int Top;         // y position of upper-left corner
    public int Right;       // x position of lower-right corner
    public int Bottom;      // y position of lower-right corner
}    

private System.IntPtr hWnd;
private void button1_Click(object sender, EventArgs e)
{
    Process p = Process.Start(@"C:\Program Files\Winamp\winamp.exe");       
    try
    {
        do
        {
            p.Refresh();
        }
        while (p.MainWindowHandle.ToInt32() == 0);

        hWnd = new IntPtr(p.MainWindowHandle.ToInt32());
    }
    catch (Exception ex)
    {
        //Do some stuff...
        throw;
    }
}

private void button2_Click(object sender, EventArgs e)
{
    //Make sure we have a handle to the shelled exe
    if (hWnd == new IntPtr(0)) return;
    ResizeExternalExeChildWindows(hWnd);
}

private void ResizeExternalExeChildWindows(IntPtr parent)
{
    List<IntPtr> childWindows = GetChildWindows(hWnd);
    foreach (IntPtr childWindow in childWindows)
    {
        RECT rect;
        GetWindowRect(childWindow, out rect);
        int width = rect.Right - rect.Left;
        int height = rect.Bottom - rect.Top;
        MoveWindow(hWnd, 0, 0, width, height, true);
    }
}

// <summary>
/// Returns a list of child windows
/// </summary>
/// <param name="parent">Parent of the windows to return</param>
/// <returns>List of child windows</returns>
public static List<IntPtr> GetChildWindows(IntPtr parent)
{
    List<IntPtr> result = new List<IntPtr>();
    GCHandle listHandle = GCHandle.Alloc(result);
    try
    {
        EnumWindowProc childProc = new EnumWindowProc(EnumWindow);
        EnumChildWindows(parent, childProc, GCHandle.ToIntPtr(listHandle));
    }
    finally
    {
        if (listHandle.IsAllocated)
            listHandle.Free();
    }
    return result;
}

/// <summary>
/// Callback method to be used when enumerating windows.
/// </summary>
/// <param name="handle">Handle of the next window</param>
/// <param name="pointer">Pointer to a GCHandle that holds a reference to the list to fill</param>
/// <returns>True to continue the enumeration, false to bail</returns>
private static bool EnumWindow(IntPtr handle, IntPtr pointer)
{
    GCHandle gch = GCHandle.FromIntPtr(pointer);
    List<IntPtr> list = gch.Target as List<IntPtr>;
if (list == null)
{
    throw new InvalidCastException("GCHandle Target could not be cast as List<IntPtr>");
}
list.Add(handle);
//  You can modify this to check to see if you want to cancel the operation, then return a null here
return true;

}

/// <summary>
/// Delegate for the EnumChildWindows method
/// </summary>
/// <param name="hWnd">Window handle</param>
/// <param name="parameter">Caller-defined variable; we use it for a pointer to our list</param>
/// <returns>True to continue enumerating, false to bail.</returns>
public delegate bool EnumWindowProc(IntPtr hWnd, IntPtr parameter);

}
}

原因

因为 WinAmp 是可换肤的,所以它支持通过配置文件调整大小(而不是通过使用 win32 API 的外部应用程序)。

解决方案

打开文件 C:\Users[用户名]\AppData\Roaming\Winamp\studio.xnf 并编辑以下值:

  <entry name="Bento_nomax_h" value="492" />
  <entry name="Bento_nomax_w" value="633" />
  <entry name="Bento_nomax_x" value="27" />
  <entry name="Bento_nomax_y" value="16" />

我正在使用 Bento Skin。如果您打开 WinAmp.ini 文件,您可以检测到正在使用的皮肤:

skin=Bento

设置 WinAmp 主窗口初始大小的解决方案是在使用 Process.Start 对 WinAmp 进行脱壳之前编辑配置文件。

关于c# 移动 Winamp 主窗口,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13157381/

相关文章:

c# - 性能和内存优化(类与结构)

c# - DllImport 在 Windows XP SP3 上失败,但在 Windows 7 上有效

html - 调整网页大小时遇到​​问题

c# - 在另一台计算机上远程连接到mysql时出现问题

c# - 从数组中选择特定数字的概率

winapi - Windows 7 功能区 UI Win32 API 代码

javascript - 使用新的宽度和高度下载调整大小的图像

css - Zurb 基金会 : How do you make buttons smaller on resize to a smaller screen?

c# - .Net Windows Forms - 在等待异步工作时限制表单导航

windows - Windows文件模式中波浪号是什么意思