it-swarm.asia

منع التطبيقات من سرقة التركيز

هل هناك أي حلول لمنع التطبيقات من سرقة التركيز من النافذة النشطة؟

هذا أمر مزعج بشكل خاص عندما أبدأ تطبيقًا ، وقم بالتبديل للقيام بشيء آخر ويبدأ التطبيق الجديد في تلقي نصف جملة نصية.

189
svandragt

هذا غير ممكن بدون واسع التلاعب في ويندوز الداخلية وتحتاج إلى تجاوزه.

هناك لحظات في استخدام الكمبيوتر اليومي عندما يكون من المهم حقًا اتخاذ إجراء قبل أن يسمح لك نظام التشغيل بالقيام بعمل آخر. للقيام بذلك ، يحتاج إلى قفل التركيز الخاص بك على بعض النوافذ. في Windows ، يتم ترك التحكم في هذا السلوك إلى حد كبير لمطوري البرامج الفردية التي تستخدمها.

ليس كل مطور يتخذ القرارات الصحيحة عندما يتعلق الأمر بهذا الموضوع.

أعرف أن هذا أمر محبط ومزعج للغاية ، لكن لا يمكنك تناول الكعك وتناوله أيضًا. من المحتمل أن يكون هناك العديد من الحالات على مدار حياتك اليومية حيث تكون على ما يرام حيث يتم نقل التركيز إلى عنصر معين من عناصر واجهة المستخدم أو طلب يظل التركيز عليه مغلقًا. لكن معظم التطبيقات متساوية إلى حد ما عندما يتعلق الأمر بتحديد الجهة التي تتقدم الآن ولا يمكن للنظام أن يكون مثاليًا أبدًا.

منذ فترة أجريت بحثًا مكثفًا حول حل هذه المشكلة مرة واحدة وإلى الأبد (وفشلت). يمكن العثور على نتيجة بحثي في ​​صفحة مشروع الانزعاج .

يتضمن المشروع أيضًا تطبيقًا يحاول مرارًا وتكرارًا جذب الانتباه من خلال الاتصال:

switch( message ) {
  case WM_TIMER:
    if( hWnd != NULL ) {
      // Start off easy
      // SetForegroundWindow will not move the window to the foreground,
      // but it will invoke FlashWindow internally and, thus, show the
      // taskbar.
      SetForegroundWindow( hWnd );

      // Our application is awesome! It must have your focus!
      SetActiveWindow( hWnd );

      // Flash that button!
      FlashWindow( hWnd, TRUE );
    }
    break;

كما نرى من هذا المقتطف ، ركزت أبحاثي أيضًا على الجوانب الأخرى لسلوك واجهة المستخدم التي لا أحبها.

كانت الطريقة التي حاولت حلها هي تحميل DLL في كل عملية جديدة وربط مكالمات API التي تسبب تنشيط نوافذ أخرى.
الجزء الأخير هو الجزء السهل ، وذلك بفضل إنشاء مكتبات API الرائعة هناك. لقد استخدمت مكتبة mhook العظيمة :

#include "stdafx.h"
#include "mhook-2.2/mhook-lib/mhook.h"

typedef NTSTATUS( WINAPI* PNT_QUERY_SYSTEM_INFORMATION ) ( 
  __in       SYSTEM_INFORMATION_CLASS SystemInformationClass,     
  __inout    PVOID SystemInformation, 
  __in       ULONG SystemInformationLength, 
  __out_opt  PULONG ReturnLength    
);

// Originals
PNT_QUERY_SYSTEM_INFORMATION OriginalFlashWindow   = 
  (PNT_QUERY_SYSTEM_INFORMATION)::GetProcAddress( 
  ::GetModuleHandle( L"user32" ), "FlashWindow" );

PNT_QUERY_SYSTEM_INFORMATION OriginalFlashWindowEx = 
  (PNT_QUERY_SYSTEM_INFORMATION)::GetProcAddress( 
  ::GetModuleHandle( L"user32" ), "FlashWindowEx" );

PNT_QUERY_SYSTEM_INFORMATION OriginalSetForegroundWindow = 
  (PNT_QUERY_SYSTEM_INFORMATION)::GetProcAddress( 
  ::GetModuleHandle( L"user32" ), "SetForegroundWindow" );

// Hooks
BOOL WINAPI
HookedFlashWindow(
  __in  HWND hWnd,
  __in  BOOL bInvert
  ) {
  return 0;
}

BOOL WINAPI 
HookedFlashWindowEx(
  __in  PFLASHWINFO pfwi
  ) {
  return 0;
}

BOOL WINAPI 
HookedSetForegroundWindow(
  __in  HWND hWnd
  ) {
  // Pretend window was brought to foreground
  return 1;
}


BOOL APIENTRY 
DllMain( 
  HMODULE hModule,
  DWORD   ul_reason_for_call,
  LPVOID  lpReserved
  ) {
  switch( ul_reason_for_call ) {
    case DLL_PROCESS_ATTACH:
      Mhook_SetHook( (PVOID*)&OriginalFlashWindow,         HookedFlashWindow );
      Mhook_SetHook( (PVOID*)&OriginalFlashWindowEx,       HookedFlashWindowEx );
      Mhook_SetHook( (PVOID*)&OriginalSetForegroundWindow, HookedSetForegroundWindow );
      break;

    case DLL_PROCESS_DETACH:
      Mhook_Unhook( (PVOID*)&OriginalFlashWindow );
      Mhook_Unhook( (PVOID*)&OriginalFlashWindowEx );
      Mhook_Unhook( (PVOID*)&OriginalSetForegroundWindow );
      break;
  }
  return TRUE;
}

من الاختبارات التي أجريتها في ذلك الوقت ، كان هذا رائعًا. باستثناء جزء من تحميل DLL في كل عملية جديدة. كما قد يتصور المرء ، هذا شيء لا يستهان به. لقد استخدمت نهج AppInit_DLLs في ذلك الوقت (والذي ببساطة لا يكفي).

في الأساس ، هذا يعمل بشكل رائع. لكنني لم أجد الوقت الكافي لكتابة شيء بشكل صحيح حقن حقلي DLL في عمليات جديدة. والوقت المستثمر في هذا يلقي بظلاله على الانزعاج الشديد الذي تسببه سرقة التركيز.

بالإضافة إلى مشكلة الحقن DLL، هناك أيضًا طريقة لسرقة التركيز لم أغطيها في تطبيق Google Code. قام أحد زملائه بالفعل بإجراء بعض الأبحاث الإضافية وقام بتغطية هذه الطريقة. تمت مناقشة المشكلة في SO: https://stackoverflow.com/questions/7430864/windows-7-prevent-application-from-losing-focus

50
Der Hochstapler

في نظام التشغيل Windows 7 ، لم يعد التحقق من إدخال التسجيل ForegroundLockTimeout ، يمكنك التحقق من ذلك باستخدام Process Monitor. في الواقع ، في Windows 7 ، لا يسمحون لك بتغيير النافذة الأمامية. اذهب واقرأ عن تفاصيلها ، لقد كانت موجودة منذ نظام التشغيل Windows 2000.

ومع ذلك ، تمتص الوثائق ويطاردون بعضهم البعض ويجدون طرقًا حول ذلك .

لذلك ، هناك شيء عربات التي تجرها الدواب يحدث مع SetForegroundWindow ، أو وظائف API مماثلة ...

الطريقة الوحيدة للقيام بذلك بشكل صحيح حقًا هي إنشاء تطبيق صغير يستدعي LockSetForegroundWindow ، تعطيل أي مكالمات تقريبًا إلى وظيفة API عربات التي تجرها الدواب.

إذا لم يكن ذلك كافيًا (مكالمة أخرى لعربات التي تجرها الدواب من API؟) يمكنك الذهاب إلى أبعد من ذلك والقيام ببعض مراقبة API لمعرفة ما يحدث ، ثم يمكنك ببساطة ربط مكالمات API في كل عملية وبعد ذلك يمكنك تخلص من أي المكالمات التي تصل الفوضى إلى المقدمة. ومع ذلك ، من المفارقات ، أن مايكروسوفت لا تشجعها ...

23
Tom Wijsman

هناك خيار في TweakUI الذي يفعل هذا. ويمنع معظم الحيل المعتادة التي يستخدمها مطورو البرمجيات المشكوك فيها لفرض التركيز على تطبيقاتهم.

إنها حرب أسلحة مستمرة ، لذلك لا أعرف ما إذا كانت تعمل من أجل كل شيء.

تحديث : وفقًا لـ EndangeredMassa ، لا يعمل TweakUI على نظام التشغيل Windows 7.

18
Simon P Stevens

أعتقد أنه قد يوجد بعض الالتباس ، حيث توجد طريقتان "لسرقة التركيز": (1) نافذة قادمة إلى المقدمة ، و (2) نافذة تلقي ضغطات المفاتيح.

ربما تكون المشكلة المشار إليها هنا هي المشكلة الثانية ، حيث تدعي النوافذ التركيز من خلال تقديم نفسها إلى المقدمة - دون طلب أو إذن من المستخدم.

يجب تقسيم المناقشة هنا بين XP و 7.

ويندوز إكس بي

في XP هناك اختراق للتسجيل يجعل XP يعمل كما هو Windows 7 في منع التطبيقات من سرقة التركيز:

  1. استخدم رجديت للذهاب إلى: HKEY_CURRENT_USER\Control Panel\Desktop.
  2. انقر نقرًا مزدوجًا على ForegroundLockTimeout وقم بتعيين قيمتها في ست عشري إلى 30d40.
  3. اضغط موافق والخروج من رجديت.
  4. أعد تشغيل الكمبيوتر لتصبح التغييرات نافذة المفعول.

ويندوز 7

(تنطبق المناقشة أدناه غالبًا على XP أيضًا.)

يرجى تفهم أنه لا توجد طريقة يمكن لـ Windows من خلالها منع التطبيقات تمامًا من سرقة التركيز والبقاء وظيفيًا. على سبيل المثال ، إذا اكتشف برنامج مكافحة الفيروسات تهديدًا محتملًا أثناء نسخة من الملفات ورغب في ظهور نافذة منبثقة تطلب منك اتخاذ الإجراء ، وإذا تم حظر هذه النافذة ، فلن تفهم أبدًا سبب عدم انتهاء النسخة.

في Windows 7 ، لا يوجد سوى تعديل واحد ممكن على سلوك Windows نفسه ، وهو استخدام الاختراقات التسجيل - الماوس - MS - Windows التركيز ، حيث ينتقل التركيز و/أو التنشيط دائما إلى النوافذ تحت المؤشر. يمكن إضافة تأخير لتجنب ظهور التطبيقات في جميع أنحاء سطح المكتب.
راجع هذه المقالة: Windows 7 - يجعل مؤشر الماوس الماوس نافذة نشطة - تمكين .

خلاف ذلك ، يجب على المرء اكتشاف وتحييد برنامج المذنب: إذا كان هذا هو دائمًا نفس التطبيق الذي يحصل على التركيز ، فسيتم برمجة هذا التطبيق بحيث يأخذ التركيز ويمنع القيام بذلك إما عن طريق تعطيله من البدء بجهاز الكمبيوتر ، أو استخدم بعض الإعدادات التي يوفرها هذا التطبيق لتجنب هذا السلوك.

يمكنك استخدام البرنامج النصي VBS المتضمن في VB الكود الذي يحدد من يسرق التركيز ، والذي استخدمه المؤلف لتحديد الجاني باعتباره "منزل استدعاء" لبرنامج تحديث الطابعة.

التدبير اليائس عندما يفشل كل شيء آخر ، وإذا كنت قد حددت هذا التطبيق الذي تمت برمجته بشكل سيء ، فهو تقليله إلى الحد الأدنى والأمل في ألا يؤدي ذلك إلى الواجهة. من أقوى أشكال التصغير هو الدرج باستخدام أحد المنتجات المجانية المدرجة في أفضل تطبيق مصغر مجاني .

الفكرة الأخيرة في ترتيب اليأس هي كسر سطح مكتبك تقريبًا باستخدام منتج مثل أجهزة سطح المكتب أو Dexpot ، وتنفيذ عملك على سطح مكتب آخر غير الافتراضي.

[تصحيح]

نظرًا لأن Microsoft قد تقاعدت في معرض الأرشيف ، فإليك الكود أعلاه [VB]:

Declare Auto Function GetForegroundWindow Lib "user32.dll" () As Integer
Declare Auto Function GetWindowThreadProcessId Lib "user32.dll" (ByVal hwnd As Integer, ByRef procid As Integer) As UInteger

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Me.RichTextBox1.AppendText("Starting up at " & Now & vbCrLf)
    End Sub

    Private Sub GoingAway(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Deactivate, Me.LostFocus

        Dim hwnd As Integer = GetForegroundWindow()
        ' Note that process_id will be used as a ByRef argument
        ' and will be changed by GetWindowThreadProcessId
        Dim process_id As Integer = 1
        GetWindowThreadProcessId(hwnd, process_id)

        If (process_id <> 1) Then
            Dim appExePath As String = Process.GetProcessById(process_id).MainModule.FileName() 
            Me.RichTextBox1.AppendText("Lost focus at " & Now & " due to " & appExePath & vbCrLf)
        Else
            Me.RichTextBox1.AppendText("Lost focus due to unknown cause.")
        End If

    End Sub
14
harrymc

مستوحاة من إجابة Der Hochstapler ، قررت أن أكتب حاقن DLL، يعمل مع كلتا العمليتين 64 و 32 بت ويمنع سرقة التركيز على Windows 7 أو أحدث: https: // blade.sk/stay-focused/

الطريقة التي تعمل بها هي مراقبة النوافذ التي تم إنشاؤها حديثًا (باستخدام SetWinEventHook) وحقن DLL تشبه إلى حد كبير نافذة Der Hochstapler في عملية النافذة إذا لم تكن موجودة بالفعل. إلغاء تحميل DLL واستعادة الوظيفة الأصلية عند الإنهاء.

من الاختبار ، يعمل بشكل جيد للغاية حتى الآن. ومع ذلك ، يبدو أن المشكلة أعمق من مجرد تطبيقات الاتصال بـ SetForegroundWindow. على سبيل المثال ، عند إنشاء نافذة جديدة ، يتم وضعها تلقائيًا في المقدمة ، والتي تتداخل أيضًا مع قيام المستخدم بالكتابة في نافذة أخرى.

للتعامل مع الطرق الأخرى لسرقة التركيز ، يلزم إجراء مزيد من الاختبارات ، وسأكون ممتناً لأي تعليقات على السيناريوهات التي تحدث.

2
blade

يحتوي Ghacks على حل ممكن:

يحدث عدة مرات في اليوم أن بعض التطبيقات تسرق تركيز الإطار النشط عن طريق الظهور. يمكن أن يحدث هذا لعدة أسباب ، عندما أقوم باستخراج الملفات أو انتهاء عملية النقل على سبيل المثال. لا يهم معظم الوقت عندما يحدث هذا ، لكن في بعض الأحيان أكتب مقالة ولا يعني ذلك فقط أن عليّ كتابة بعض الكلمات مرة أخرى ولكن أيضًا فقد التركيز وتركي للنقر لاستعادة التركيز.

يحتوي Pro Pro موقع الويب على معلومات حول كيفية منع حدوث ذلك. تتمثل أسهل طريقة لمنع سرقة التركيز في استخدام Tweak UI الذي يحتوي على إعداد يسمى "منع التطبيقات من سرقة التركيز". يؤدي تحديد هذا الخيار إلى منع ظهور التطبيقات الأخرى بشكل مفاجئ وسرقة تركيز النافذة التي تعمل بها حاليًا.

هذا يعمل فقط عندما تم تصغير التطبيق من قبل. بدلاً من سرقة التركيز ، سيتم وميض عدد من المرات التي يمكن تعريفها في نفس القائمة في Tweak UI . إذا كنت لا ترغب في استخدام Tweak UI ، فيمكنك تغيير الإعداد في تسجيل Windows.

انتقل إلى مفتاح التسجيل HKEY_CURRENT_USER> لوحة التحكم> سطح المكتب وقم بتغيير قيمة ForegroundLockTimeout إلى 30d40 (سداسي عشري) أو 200000 (عشري). يعرّف المفتاح ForeGroundFlashCount مقدار ومضات إطار لتنبيه المستخدم حيث 0 يعني غير محدود.

2
Ivo Flipse

لقد اكتشفت كيفية منع شريط المهام من وميض نافذة هدف تم تنشيطها حديثًا بعد قيامك بتنشيط الإطار الرئيسي لتلك العملية وتعظيمه وتركيزه من عملية أخرى بشكل برمجي. بادئ ذي بدء ، هناك الكثير من القيود على ما إذا كان سيتم السماح بهذه العملية.

"يقيد النظام العمليات التي يمكنها تعيين نافذة المقدمة. يمكن أن تحدد العملية نافذة المقدمة فقط إذا كان أحد الشروط التالية صحيحاً:

  • العملية هي العملية الأمامية.
  • بدأت العملية من خلال عملية المقدمة.
  • تلقت العملية حدث الإدخال الأخير.
  • لا توجد عملية في المقدمة.
  • يتم الآن تصحيح عملية المقدمة.
  • لم يتم تأمين المقدمة (انظر LockSetForegroundWindow).
  • انتهت مهلة قفل المقدمة (راجع SPI_GETFOREGROUNDLOCKTIMEOUT في SystemParametersInfo).
  • لا توجد قوائم نشطة.

https://docs.Microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-allowsetforegroundwindow

لذلك إذا كانتالتحكمالعملية في المقدمة ، فيمكنها مؤقتًا تمكين عملية أخرى لسرقة المقدمة بالكامل عن طريق الاتصال AllowSetForegroundWindow مع معرف العملية العملية المستهدفة. بعد ذلك ، يمكن للعملية الهدف استدعاء SetForegroundWindow نفسها ، باستخدام مقبض النافذة الخاص بها ، وستعمل.

من الواضح ، أن هذا يتطلب بعض التنسيق بين العمليتين ، ولكنه يعمل ، وإذا كنت تقوم بذلك من أجل تطبيق تطبيق مثيل واحد الذي يعيد توجيه جميع عمليات إطلاق النقر فوق Explorer في مثيل التطبيق الحالي ، ثم سيكون لديك بالفعل (على سبيل المثال) أنبوب مسمى لتنسيق الأشياء على أي حال.

0
Glenn Slayden