2010-09-22 35 views
12

Tôi có một loạt các ứng dụng khá phức tạp phụ thuộc vào khả năng chuyển đổi các ứng dụng ở nền trước.Win32 SetForegroundWindow không đáng tin cậy

Vấn đề của tôi là mỗi 5 hoặc 6 lần chuyển đổi các ứng dụng ở nền trước, nó đơn giản là không đưa ứng dụng lên phía trước. GetLastError không báo cáo bất kỳ vấn đề nào. Thông thường, tôi thấy đèn flash ứng dụng chính xác ở nền trước trong giây lát thì ứng dụng trước đó có thể nhìn thấy.

Tôi có ứng dụng Trình quản lý mà tôi có nguồn, nó sinh ra và kiểm soát khoảng 4 ứng dụng mà tôi không có nguồn. một trong những ứng dụng mà nó sinh ra/điều khiển cũng là một người quản lý để sinh ra/kiểm soát khoảng 5 ứng dụng.

Đây là một loại thiết kế kiosk để người dùng thậm chí không có bàn phím hoặc chuột, chỉ cần một màn hình cảm ứng.

Tôi đã thử mọi sự kết hợp của các cuộc gọi Win32 để kiểm soát chúng tôi chỉ là ngoài ý tưởng.

nỗ lực đầu tiên của tôi là:

SetWindowPos(hApp, HWND_TOPMOST, NULL, NULL, NULL, NULL, SWP_NOMOVE | SWP_NOSIZE); 
SetWindowPos(hApp, HWND_NOTOPMOST, NULL, NULL, NULL, NULL, SWP_NOMOVE | SWP_NOSIZE); 

nỗ lực thứ hai của tôi là:

SetForegroundWindow(hApp); 
SetActiveWindow(hApp); 
SetFocus(hApp); 

nỗ lực thứ ba của tôi: DWORD dwThreadID = GetWindowThreadProcessId (Happ, NULL); AttachThreadInput (dwThreadID, GetCurrentThreadId(), true);

SetForegroundWindow(hApp); 
SetActiveWindow(hApp); 
SetFocus(hApp); 

AttachThreadInput(dwThreadID, GetCurrentThreadId(), false); 

nỗ lực ra tôi:

DWORD dwThreadID = GetWindowThreadProcessId(hApp, NULL); 
AttachThreadInput(dwThreadID, GetCurrentThreadId(), true); 

SetWindowPos(hApp, HWND_TOPMOST, NULL, NULL, NULL, NULL, SWP_NOMOVE | SWP_NOSIZE); 
SetWindowPos(hApp, HWND_NOTOPMOST, NULL, NULL, NULL, NULL, SWP_NOMOVE | SWP_NOSIZE); 

SetForegroundWindow(hApp); 
SetActiveWindow(hApp); 
SetFocus(hApp); 

AttachThreadInput(dwThreadID, GetCurrentThreadId(), false); 

tôi cảm thấy như tôi đang thiếu một Gotcha quan trọng khi nói đến việc chuyển đổi cửa sổ. Tôi biết rằng chỉ có quy trình nền trước mới có thể chuyển đổi cửa sổ nhưng chương trình chính của tôi là sinh sản và bắt đầu tất cả các quy trình khác mà tôi cần kiểm soát, tôi cảm thấy nó có khả năng di chuyển các cửa sổ này xung quanh. Bất kỳ đề xuất hoặc lời khuyên nào được đánh giá cao.

+2

Đầu tiên bước, đọc và hiểu điều này: http://blogs.msdn.com/b/oldnewthing/archive/2009/02/20/9435239.aspx –

+0

Ngoài ra: http://blogs.msdn.com/b/oldnewthing/archive /2008/08/01/8795860.aspx –

+0

Hãy thử giảm thiểu theo sau bằng cách khôi phục. –

Trả lời

4

Tệp đính kèm AttachThreadInput() của bạn là (tôi nghĩ) một cách được biết để đánh bại trọng tâm lấy cắp các biện pháp chống truy cập trong Windows. Tuy nhiên, bạn đang sử dụng trình xử lý sai, bạn muốn đính kèm vào chuỗi hiện có tiêu điểm. Mà sẽ không được hApp, bạn sẽ không cần mã này nếu không.

Sử dụng GetForegroundWindow() để xử lý cửa sổ bằng tiêu điểm.

AttachThreadInput(
    GetWindowThreadProcessId(GetForegroundWindow(), NULL), 
    GetCurrentThreadId(), TRUE 
); 

Mặc dù tôi nghĩ đối số thứ 2 cần phải là ID chủ đề của hApp. Bởi vì bạn không muốn xô cửa sổ của riêng bạn nếu tôi hiểu chính xác. Không chắc chắn nếu điều đó có thể làm việc.

+0

Đây chắc chắn là một hack mà tôi đang sử dụng như một phương sách cuối cùng, tôi không chắc chắn lý do tại sao tôi sẽ cần phải đính kèm vào quá trình Foreground vì tất cả mọi thứ trong Foreground là một đứa trẻ của ứng dụng quản lý của tôi. Có lẽ điều tôi đang làm là làm mất tập trung. Cảm ơn bạn đã xác định lỗi, tôi thực sự hy vọng đây là vấn đề! –

+0

Tôi nghĩ rằng điều này chủ yếu là giải quyết vấn đề của tôi, tôi vẫn còn có một vấn đề thỉnh thoảng nhưng những gì đã kết thúc làm một cái gì đó như: cho tôi 0-3 và thực hiện gắn vào sợi bộ như đầu nhất bộ như đầu Mở cửa sổ mới nếu getforegroundwindow = app done = true –

+2

Hack này [có thể khiến chương trình của bạn bị treo] (http://blogs.msdn.com/b/oldnewthing/archive/2008/08/01/8795860.aspx) – MarkJ

0

Trước tiên hãy thử đẩy các cửa sổ ứng dụng khác lên nền.

Cũng hơi lạ một chút khi bạn sử dụng SetWindowPos (SWP) để đẩy cửa sổ lên nền trước rồi đẩy nó ra khỏi phần trước khi sử dụng SetForegroundWindow để đưa nó trở lại foward. Cá nhân tôi đã luôn luôn sử dụng phương pháp SWP mà không có bất kỳ vấn đề ... nhưng tôi đã luôn luôn đẩy các cửa sổ khác để phía dưới là tốt.

+0

Bạn có đề cập đến NOTOPMOST sau TOPMOST? –

1

Chúng tôi đã gặp sự cố tương tự vài năm trước.Chúng tôi có thể giải quyết bằng cách gọi hàm sau:

SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, 0, SPIF_UPDATEINIFILE); 

Hãy thử. Xem tài liệu here.

+0

Tôi đang thiết lập ForegroundLocktimeout trong sổ đăng ký, nó có giống nhau không? –

+0

Tôi vừa gọi là 'SystemParametersInfo (SPI_SETFOREGROUNDLOCKTIMEOUT, 0, 0, SPIF_UPDATEINIFILE)' và nó đã đặt 'HKEY_CURRENT_USER \ Control Panel \ Desktop \ ForegroundLockTimeout' thành 0. – Bill

+0

Bạn cũng có thể tham khảo liên kết này để được trợ giúp thêm: http://www.codeproject.com/Tips/76427/How-to-bring-window-to-top-with-SetForegroundWindo – Ankur

2

Một số cửa sổ bị khóa với setforeground (...), bạn cần mở khóa chúng. Chuỗi này hữu ích với bất kỳ cửa sổ nào:

HWND needTopWindow=FindWindow(TEXT("classname"), TEXT("window name")); 

tên lớp và tên cửa sổ bạn có thể truy xuất bằng ranorexspy từ ví dụ: nanoware.cz

if(!::IsWindow(needTopWindow)) return; 

BYTE keyState[256] = {0}; 
//to unlock SetForegroundWindow we need to imitate Alt pressing 
if(::GetKeyboardState((LPBYTE)&keyState)) 
    { 
    if(!(keyState[VK_MENU] & 0x80)) 
     { 
     ::keybd_event(VK_MENU, 0, KEYEVENTF_EXTENDEDKEY | 0, 0); 
     } 
    } 

    ::SetForegroundWindow(needTopWindow); 

if(::GetKeyboardState((LPBYTE)&keyState)) 
    { 
     if(!(keyState[VK_MENU] & 0x80)) 
     { 
      ::keybd_event(VK_MENU, 0, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0); 
     } 
    } 


     DWORD dwThreadID = GetWindowThreadProcessId(needTopWindow, NULL); 
     AttachThreadInput(dwThreadID, GetCurrentThreadId(), true); 

     SetWindowPos(needTopWindow, HWND_TOPMOST, NULL, NULL, NULL, NULL, SWP_NOMOVE | SWP_NOSIZE); 
     SetWindowPos(needTopWindow, HWND_NOTOPMOST, NULL, NULL, NULL, NULL, SWP_NOMOVE | SWP_NOSIZE); 

     SetForegroundWindow(needTopWindow); 
     SetActiveWindow(needTopWindow); 
     SetFocus(needTopWindow); 

     AttachThreadInput(dwThreadID, GetCurrentThreadId(), false); 
9

Tôi đã có cùng một vấn đề và tôi không muốn gây rối với chủ đề. Khi thử nghiệm, tôi đã quan sát một hack đơn giản để làm cho SetForegroundWindow() hoạt động theo cách mong đợi. Dưới đây là những gì tôi đã làm:

  1. Giảm thiểu các cửa sổ nếu nó vẫn chưa giảm thiểu
  2. Khôi phục các cửa sổ thu nhỏ
  3. Gọi SetForegroundWindow(), và cửa sổ của bạn sẽ được trên đầu
0

Bạn cũng có cần phải xem xét các cơ hội của cửa sổ được giảm thiểu. Nếu cửa sổ hoặc ứng dụng khác nhau được giảm thiểu thì SetForegroundWindow (hApp) sẽ không hoạt động. Để sử dụng an toàn ShowWindow (hApp, 9); Tôi thích giá trị 9. Có một cái nhìn tại tài liệu của nó và chọn mà bạn tìm thấy phù hợp cho bạn.

+0

Tôi thích các hằng số biểu tượng. Nghiêm túc, đây là năm 2015, và bạn vẫn ** sử dụng ma thuật? Có gì sai với 'SW_RESTORE'? – IInspectable

1

Giải pháp đơn giản nhất trong C# để mang lại một cửa sổ ở mặt trước:

Một khi bạn có tay cầm cho cửa sổ, bạn có thể chỉ cần gọi:

SetWindowPos(handle, new IntPtr(0), 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW); 
    ShowWindow(handle, 5); 
    SetForegroundWindow(handle); 

    // If it is minimized, show the window 
    if (IsIconic(handle)) 
    { 
     ShowWindow(handle, 3); 
    } 

nơi

const int SWP_NOMOVE = 0x0002; 
const int SWP_NOSIZE = 0x0001; 
const int SWP_SHOWWINDOW = 0x0040; 
Các vấn đề liên quan