2012-10-31 74 views
3

我試圖移動winamps主窗口,使用此代碼:C#移動的Winamp主窗口

[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一起工作?

+2

你會希望做一個GetWindowLong沒有HWND的檢查窗口實際上是可調整大小。 Winamp被skinnable我懷疑是技術上不可調整大小(因爲這樣),因爲它處理一切本身。 – PhonicUK

+0

我得到了一個句柄,但即使改變尺寸,尺寸也是一樣的。該窗口不移動或調整大小(此代碼不會調整窗口大小,但我也嘗試過) –

+0

GetWindowRect返回正確的顯示大小嗎?也許MainWindowHandle不是正確的句柄。 – Benjamin

回答

1

用下面的代碼,我可以確認更改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:\用戶[用戶名] \應用程序數據\漫遊\ 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" /> 

我使用的盒飯皮膚。如果打開WinAmp.ini文件,你可以檢測皮膚使用:

皮膚=盒飯

設置爲Winamp的主窗口的初始大小的解決方案是炮擊之前編輯配置文件WinAmp與Process.Start

1

我試過了你的代碼,它並不總是工作,它不是重新調整窗口大小,它只是移動它, 其實我在2000毫秒的睡眠中發現了一個問題,你可以改變一陣子循環檢查,如果該句柄爲零,則用代碼進行,

while (p.MainWindowHandle == 0) 
{ 
} 
IntPtr hWnd = p.MainWindowHandle; 

如果AOL的Winamp需要太多的時間來建立其自己的窗口

+0

你用Winamp試過了嗎?因爲在我的情況下,當我插入代碼時,它會移動別的東西,它將一個較舊的窗口移動到位置0 0,當我彈出它時消失 –

+0

我已經嘗試了與其他應用程序的代碼,可能是winamp的主要模塊不是我們看到的!我不確定這一點,但要確定錯誤在哪裏,您可以啓動除winamp以外的其他應用程序,或使應用程序使用計時器打印前景句柄,以便它可以在後臺運行並與主句柄進行比較winamp的過程 –

+0

對不起,很長的延遲,我試過它與前景句柄,他們是不同的 –

1

這使用最新版本的工作對我來說,請試試看:

internal struct RECT 
    { 
     public int left; 
     public int top; 
     public int right; 
     public int bottom; 
    } 

    [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall, ExactSpelling = true, SetLastError = true)] 
    internal static extern bool GetWindowRect(IntPtr hWnd, ref RECT rect); 

    [DllImport("user32.dll")] 
    [return: MarshalAs(UnmanagedType.Bool)] 
    static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, SetWindowPosFlags uFlags); 

    public static class HWND 
    { 
     public static IntPtr 
     NoTopMost = new IntPtr(-2), 
     TopMost = new IntPtr(-1), 
     Top = new IntPtr(0), 
     Bottom = new IntPtr(1); 
    } 

    [Flags] 
    public enum SetWindowPosFlags : uint 
    { 
     SWP_ASYNCWINDOWPOS = 0x4000, 
     SWP_DEFERERASE = 0x2000, 
     SWP_DRAWFRAME = 0x0020, 
     SWP_FRAMECHANGED = 0x0020, 
     SWP_HIDEWINDOW = 0x0080, 
     SWP_NOACTIVATE = 0x0010, 
     SWP_NOCOPYBITS = 0x0100, 
     SWP_NOMOVE = 0x0002, 
     SWP_NOOWNERZORDER = 0x0200, 
     SWP_NOREDRAW = 0x0008, 
     SWP_NOREPOSITION = 0x0200, 
     SWP_NOSENDCHANGING = 0x0400, 
     SWP_NOSIZE = 0x0001, 
     SWP_NOZORDER = 0x0004, 
     SWP_SHOWWINDOW = 0x0040, 
    } 

    [DllImport("user32.dll", SetLastError = true)] 
    private static extern IntPtr FindWindow(string lpClassName, string lpWindowName); 

    static void Resize() 
    { 
     IntPtr winampMainWindow = IntPtr.Zero; 

     while (true) 
     { 
      winampMainWindow = FindWindow("BaseWindow_RootWnd", "Main Window"); 
      if (winampMainWindow != IntPtr.Zero) 
      { 
       RECT rect = new RECT(); 
       GetWindowRect(winampMainWindow, ref rect); 
       int width = rect.right - rect.left; 
       int height = rect.bottom - rect.top; 
       SetWindowPos(winampMainWindow, 
        HWND.Top, 
        0, 
        0, 
        width, 
        height, 
        SetWindowPosFlags.SWP_SHOWWINDOW | SetWindowPosFlags.SWP_NOZORDER | SetWindowPosFlags.SWP_NOSIZE | SetWindowPosFlags.SWP_NOSENDCHANGING | SetWindowPosFlags.SWP_NOOWNERZORDER | SetWindowPosFlags.SWP_NOCOPYBITS); 
       break; 
      } 
      Thread.Sleep(1000); 
     } 
    } 

    [STAThread] 
    static void Main() 
    { 
     Process.Start("winamp.exe"); 
     Resize(); 
    } 
+0

我用的版本是5.63不同的皮膚,可悲的是什麼也沒發生 –

+0

由於你已經把問題標記爲回答我不會就此提供進一步的答案。 –

+0

@Żubrówka - 分享你的研究可以幫助每個人。當有人標記答案時,他們以後可以改變主意,我已經做了幾次。 –