2012-12-07 47 views
0

我會對標題中的實際問題給出一些說明,但我無法弄清楚它是什麼。我所能說的是,當我試圖爲變量賦值時,該窗體在實現應用欄時不再響應,從而導致我不得不停止調試並重新啓動機器以重新獲得桌面工作區域。錯誤的位置在下面的代碼中註明,我只列出了錯誤代碼。這裏有什麼明顯的東西,我沒有看到?Windows窗體桌面應用程序欄未響應

static class Program 
{ 
    [STAThread] 
    static void Main() 
    { 
     Application.EnableVisualStyles(); 
     Application.SetCompatibleTextRenderingDefault(false); 
     Application.Run(new Form1()); 
    } 
} 

public partial class Form1 : AppBar 
{ 
    public Form1() : base() 
    { 
     InitializeComponent(); 
    } 

    //This is a button on the test form. 
    //When clicked, the form should become a desktop application bar 
    //docked to the top of the desktop. 
    private void t_Click(object sender, EventArgs e) 
    { 
     base.SET_APPBAR(); 
    } 
} 

public class AppBar : Form 
{ 
    protected internal Size appbarSize; 
    protected internal Point appbarLocation; 
    protected internal bool appbarMode; 
    private EDGES appbarEdge; 
    private RECT appbarRect; 

    private uint ID { get; private set; } 
    private IntPtr HANDLE { get; private set; } 

    //constructor 
    public AppBar() : base() //no issues here 
    { 
     appbarEdge = EDGES.ABE_TOP; 
     appbarRect = new RECT(); 
     ID = 0; 
     HANDLE = this.Handle; 
     appbarMode = false; 
    } 

    protected internal void SET_APPBAR() 
    { 
     if (IS_NEW()) 
     { 
      QUERY_AND_SET_POSITION(ref appbarRect); //Never get to here 
     } 
    } 

    private bool IS_NEW() 
    { 
     if (appbarMode) //so far, so good 
     { 
      return false; 
     } 
     while (ID == 0) 
     { 
      CREATE_ID(); //ID is created, I have verified this. 
     } 
     this.FormBorderStyle = FormBorderStyle.FixedToolWindow; //BorderStyle does change 
     appbarSize = this.Size; //Size is correct 
     appbarLocation = this.Location; //still no issues 
     NEW(); //this is where the error begins (see code further down) 
     return appbarMode; //Never get here 
    } 

    private void CREATE_ID() 
    { 
     ID = Hooks.RegisterWindowMessage(Guid.NewGuid().ToString()); 
    } 

    private void QUERY_AND_SET_POSITION(ref RECT appbarRect) 
    { 
     SET_APPBAR_SIZE(ref appbarRect); 
     QUERY_POS(ref appbarRect); 
     APPBAR_RESIZE(ref appbarRect); 
     SET_POS(ref appbarRect); 
     this.Location = new Point(appbarRect.left, appbarRect.top); 
     appbarSize = new Size(appbarRect.right - appbarRect.left, appbarRect.bottom - appbarRect.top); 
     this.Size = appbarSize; 
    } 

    private void SET_APPBAR_SIZE(ref RECT appbarRect) 
    { 
     switch (appbarEdge) 
     { 
      case (EDGES.ABE_BOTTOM): 
       appbarRect.left = 0; 
       appbarRect.right = SystemInformation.PrimaryMonitorSize.Width; 
       appbarRect.top = SystemInformation.PrimaryMonitorSize.Height - appbarSize.Height; 
       appbarRect.bottom = SystemInformation.PrimaryMonitorSize.Height; 
       break; 
      case (EDGES.ABE_LEFT): 
       appbarRect.left = 0; 
       appbarRect.right = appbarSize.Width; 
       appbarRect.top = 0; 
       appbarRect.bottom = SystemInformation.PrimaryMonitorSize.Height; 
       break; 
      case (EDGES.ABE_RIGHT): 
       appbarRect.left = SystemInformation.PrimaryMonitorSize.Width - appbarSize.Width; 
       appbarRect.right = SystemInformation.PrimaryMonitorSize.Width; 
       appbarRect.top = 0; 
       appbarRect.bottom = SystemInformation.PrimaryMonitorSize.Height; 
       break; 
      default: 
       appbarRect.left = 0; 
       appbarRect.right = SystemInformation.PrimaryMonitorSize.Width; 
       appbarRect.top = SystemInformation.WorkingArea.Top; 
       appbarRect.bottom = appbarSize.Height; 
       break; 
     } 
    } 

    private void APPBAR_RESIZE(ref RECT appbarRect) 
    { 
     switch (appbarEdge) 
     { 
      case (EDGES.ABE_TOP): 
       appbarRect.bottom = appbarRect.top + appbarSize.Height; 
       break; 
      case (EDGES.ABE_BOTTOM): 
       appbarRect.top = appbarRect.bottom - appbarSize.Height; 
       break; 
      case (EDGES.ABE_LEFT): 
       appbarRect.right = appbarRect.left + appbarSize.Width; 
       break; 
      case (EDGES.ABE_RIGHT): 
       appbarRect.left = appbarRect.right - appbarSize.Width; 
       break; 
     } 
    } 

    private void APPBAR_CALLBACK(ref Message apiMessage) 
    { 
     switch ((NOTIFICATIONS)(uint)apiMessage.WParam)//? on int vs uint here 
     { 
      case (NOTIFICATIONS.ABN_STATECHANGE): 
       STATE_CHANGE(); 
       break; 
      case (NOTIFICATIONS.ABN_POSCHANGED): 
       QUERY_AND_SET_POSITION(ref appbarRect); 
       break; 
      case (NOTIFICATIONS.ABN_FULLSCREENAPP): 
       if ((int)apiMessage.LParam != 0) 
       { 
        this.SendToBack(); 
        this.TopMost = false; 
       } 
       else 
       { 
        STATE_CHANGE(); 
       } 
       break; 
      case (NOTIFICATIONS.ABN_WINDOWARRANGE): 
       //first call 
       if ((int)apiMessage.LParam != 0) 
       { 
        this.Visible = false; 
       } 
       //second call 
       else 
       { 
        this.Visible = true; 
       } 
       break; 
     } 
    } 

    protected override void WndProc(ref Message apiMessage) 
    { 
     if (appbarMode) 
     { 
      if (HANDLE == apiMessage.HWnd) 
      { 
       APPBAR_CALLBACK(ref apiMessage); 
      } 
      else if (apiMessage.Msg == (int)API_MESSAGES.WM_ACTIVATE) 
      { 
       ACTIVATE(); 
      } 
      else if (apiMessage.Msg == (int)API_MESSAGES.WM_WINDOWPOSCHANGED) 
      { 
       WINDOW_POS_CHANGED(); 
      } 
     } 
     base.WndProc(ref apiMessage); 
    } 

    private void NEW() 
    { 
     APPBARDATA data = new APPBARDATA(); //no apparent issue 
     data.cbSize = (uint)Marshal.SizeOf(data); //no apparent issue 
     data.hWnd = HANDLE; //no apparent issue 
     data.uCallbackMessage = ID; //no apparent issue 
     if (Hooks.SHAppBarMessage((uint)DWORD.ABM_NEW, ref data) != 0) //SHAppBar returns 1 (true) 
     { 
      //no issue if I were to place a MessageBox here 
      appbarMode = true; // why in the world is this causing an issue????? 
      //can't do anything from this point 
     } 
    } 
} 

public static class Hooks 
{ 
    [DllImport("shell32.dll", EntryPoint = "SHAppBarMessage")] 
    public static extern uint SHAppBarMessage(uint dwMessage, ref APPBARDATA pData); 

    [DllImport("user32.dll", EntryPoint = "RegisterWindowMessage")] 
    public static extern uint RegisterWindowMessage(
     [MarshalAs(UnmanagedType.LPTStr)] 
     string lpString); 
} 

無論發生什麼問題,我都無法點擊任何按鈕或關閉窗體。桌面工作區域總是適當調整大小。希望這對所有人都有意義。感謝您提前看。

回答

3

問題是,您正在UI線程中執行長時間運行的操作。這會阻止UI線程並阻止其執行其他任何操作(從繪製更改,響應按鈕單擊或鼠標移動事件等)。

您需要在後臺線程中執行您的長時間運行操作。雖然您可以手動執行此操作,但使用BackgroundWorker更好,因爲它專門用於此應用程序。它不僅可以爲你創建/配置後臺線程,而且它提供了簡單易用的機制,用於在完成後臺任務時更新UI,在任務正在工作時更新UI以及進度等。

請注意,在後臺線程中,您無法訪問UI元素;他們需要從UI線程訪問。您應該將所有從UI獲取信息的代碼移動到開始後臺任務之前(稍後將其保存在本地變量或字段中),並且您應該移動所有代碼以基於結果更新UI(在RunWorkerCompleted事件,如果使用BackgroundWorker)。除DoWork之外的所有事件BackgroundWorker都在UI線程中執行,因此可以訪問您的UI控件。

+0

呵呵呵。我認爲我未來的「實施多線程」預發佈說明只是向上移動隊列。感謝您的洞察力。 – Tebc

+0

任何人都應該關注這個,你可能也對這個老的線程感興趣:http://stackoverflow.com/questions/3286373/flickering-in-a-windows-forms-app – Tebc

相關問題