ফোকাস চুরি না করে একটি ফর্ম প্রদর্শন করবেন?


140

আমি বিজ্ঞপ্তিগুলি দেখানোর জন্য একটি ফর্ম ব্যবহার করছি (এটি স্ক্রিনের নীচে ডানদিকে প্রদর্শিত হবে) তবে আমি যখন এই ফর্মটি দেখাব তখন এটি মূল ফর্মটি থেকে ফোকাসটি চুরি করে। চেক ফোকাস না করে এই "বিজ্ঞপ্তি" ফর্মটি দেখানোর কোনও উপায় আছে কি?

উত্তর:


165

হুমমম, কেবল ফর্মকে ওভাররাইড করছে না? প্রদর্শনী ছাড়া কী যথেষ্ট?

protected override bool ShowWithoutActivation
{
  get { return true; }
}

এবং যদি আপনি না চান যে ব্যবহারকারী এই নোটিফিকেশন উইন্ডোতে ক্লিক করুন তবে আপনি ক্রিয়েটপ্যারামগুলি ওভাররাইড করতে পারেন:

protected override CreateParams CreateParams
{
  get
  {
    CreateParams baseParams = base.CreateParams;

    const int WS_EX_NOACTIVATE = 0x08000000;
    const int WS_EX_TOOLWINDOW = 0x00000080;
    baseParams.ExStyle |= ( int )( WS_EX_NOACTIVATE | WS_EX_TOOLWINDOW );

    return baseParams;
  }
}

3
শো উইথআউট অ্যাক্টিভেশন, বিশ্বাস করতে পারি না যে আমি এটি পাইনি, পুরো দুপুরে নষ্ট!
ডিয়ারচাও

2
form1.Enabled = falseঅভ্যন্তরীণ নিয়ন্ত্রণগুলি চুরির ফোকাস থেকে রোধ করার জন্য আমারও সেট করা দরকার ছিল
জেডার ডায়াস

23
এবং টপমস্টকে ছেড়ে দিন।
mklein

4
এবং আপনি যদি টপমোস্ট চান তবে অন্য উত্তরটি দেখুন
রোমান স্টারকভ

2
মান WS_EX_NOACTIVATEএবং WS_EX_TOOLWINDOWহয় 0x08000000এবং 0x00000080যথাক্রমে।
জুয়ান

69

থেকে চুরি PInvoke.net এর ShowWindow পদ্ধতি:

private const int SW_SHOWNOACTIVATE = 4;
private const int HWND_TOPMOST = -1;
private const uint SWP_NOACTIVATE = 0x0010;

[DllImport("user32.dll", EntryPoint = "SetWindowPos")]
static extern bool SetWindowPos(
     int hWnd,             // Window handle
     int hWndInsertAfter,  // Placement-order handle
     int X,                // Horizontal position
     int Y,                // Vertical position
     int cx,               // Width
     int cy,               // Height
     uint uFlags);         // Window positioning flags

[DllImport("user32.dll")]
static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);

static void ShowInactiveTopmost(Form frm)
{
     ShowWindow(frm.Handle, SW_SHOWNOACTIVATE);
     SetWindowPos(frm.Handle.ToInt32(), HWND_TOPMOST,
     frm.Left, frm.Top, frm.Width, frm.Height,
     SWP_NOACTIVATE);
}

(অ্যালেক্স লাইম্যান এটার জবাব দিলেন, আমি কেবল কোডটি সরাসরি পেস্ট করে এটিকে প্রসারিত করছি edit সম্পাদনা অধিকার সহ কেউ এটিকে সেখানে অনুলিপি করতে পারেন এবং এটি আমার যত্নের জন্য মুছে ফেলতে পারেন;))


আমি ভাবছিলাম, তাঁর কি সত্যিই দরকার আছে যে ফর্মটি যদি তিনি তার পর্দার নীচে বাম দিকে প্রদর্শিত হয় তবে এটি অন্য থ্রেডে রয়েছে?
প্যাট্রিক দেশজার্ডিনস

50
আমি এটি অবিশ্বাস্য মনে করি যে ফর্মগুলির সাথে যোগাযোগের জন্য আমাদের এখনও বাহ্যিক ডিএলএল ফাইলগুলির সাথে লিঙ্ক করতে হবে। আমরা .NET ফ্রেমওয়ার্ক সংস্করণ 4 এ আছি! মাইক্রোসফ্ট এটি মোড়ানো সময়।
মালট্র্যাপ

9
গৃহীত উত্তরটি ভুল। শো উইথআউট অ্যাক্টিভেশন সন্ধান করুন
mklein

শুধু frm.Hide () যোগ করুন ; আপনি যদি আপনার ফর্মটি সরাসরি ফোকাসবিহীন করতে চান তবে শোআইএনএটিভটিভোস্টোম ফাংশনের শুরুতে। ভুলে যাবেন না: System.Runtime.InteropServices ব্যবহার করে; এই কোডটি চলমান করতে
জিটুন

1
@ তালহা এই কোডটির লোড ইভেন্টের সাথে কোনও সম্পর্ক নেই। ফর্মটি লোড করা হচ্ছে এমন সময় লোড ইভেন্টটি দগ্ধ হয়, যখন দেখানো হচ্ছে না।
TheSoftwareJedi


12

এটিই আমার পক্ষে কাজ করেছিল। এটি টপমস্ট সরবরাহ করে তবে ফোকাস-চুরি ছাড়াই।

    protected override bool ShowWithoutActivation
    {
       get { return true; }
    }

    private const int WS_EX_TOPMOST = 0x00000008;
    protected override CreateParams CreateParams
    {
       get
       {
          CreateParams createParams = base.CreateParams;
          createParams.ExStyle |= WS_EX_TOPMOST;
          return createParams;
       }
    }

ভিজ্যুয়াল স্টুডিও ডিজাইনার বা অন্য কোথাও টপমস্ট সেট করা বাদ দিতে ভুলবেন না।

এটি এখান থেকে চুরি, ত্রুটিযুক্ত, ধার করা হয়েছে (ওয়ার্কারাউন্ডে ক্লিক করুন):

https://connect.microsoft.com/VisualStudio/feedback/details/401311/showwithoutactivation-is-not-supported-with-topmost


1
শীর্ষস্থানীয় + ফোকাসবিহীন কাজ করে এবং এটি সমস্ত উত্তরগুলির মধ্যে সবচেয়ে পরিষ্কার বলে মনে হয়।
ফিজ

উইন্ডোজ 8-এর পর থেকে শীর্ষগুলি অবহিত করা হয়েছে যেখানে মাইক্রোসফ্ট এটি ব্যবহার করার সময় আপনাকে শাস্তি দেয়। এর প্রভাবটি হ'ল একটি শীর্ষতম উইন্ডোটি খোলার পরে এবং এটি বন্ধ করার পরে, উইন্ডোজ আপনার অ্যাপ্লিকেশনটির অন্যান্য উইন্ডোজটিকে পটভূমিতে সরিয়ে দেয়। এটি অবশ্যই আপনার আবেদনের জন্য পছন্দসই আচরণ নয়। মাইক্রোসফ্ট এটি বাস্তবায়িত করেছিল কারণ অতীতে অনেক প্রোগ্রামাররা খুব হস্তক্ষেপকারী শীর্ষস্থানীয়কে আপত্তি জানায়। শীর্ষস্থানীয় খুব আক্রমণাত্মক। আমি কখনই এটি ব্যবহার করি না।
এলময়ে

9

এটি করা হ্যাকের মতো মনে হলেও এটি কার্যকর হবে বলে মনে হচ্ছে:

this.TopMost = true;  // as a result the form gets thrown to the front
this.TopMost = false; // but we don't actually want our form to always be on top

সম্পাদনা: দ্রষ্টব্য, এটি কেবল ফোকাস চুরি না করে ইতিমধ্যে তৈরি ফর্মটি উত্থাপন করে।


মনে হচ্ছে না এখানে কাজ করছে ... কারণ এটি "সূচিত ফর্ম" অন্য থ্রেডে খোলা আছে?
Matías

1
সম্ভবত, সেক্ষেত্রে আপনাকে এটি করতে হবে the পদ্ধতিটিকে আবার সঠিক থ্রেড হিসাবে কল করার জন্য আহ্বান করা () কল করতে হবে। সাধারণত ভুল থ্রেড থেকে ফর্মগুলির সাথে কাজ করার কারণে যদিও ব্যতিক্রম ছুঁড়ে ফেলা হয়।
ম্যাথু শার্লে 4

যদিও এটি কাজ করে, এটি উল্লিখিত হিসাবে একটি হ্যাকি পদ্ধতি এবং নির্দিষ্ট শর্তে আমার জন্য বিএসওডের কারণ ঘটেছে, সুতরাং এ থেকে সাবধান থাকুন।
রাফেল স্মিট

উইন্ডোজ 8-এর পর থেকে শীর্ষগুলি অবহিত করা হয়েছে যেখানে মাইক্রোসফ্ট এটি ব্যবহার করার সময় আপনাকে শাস্তি দেয়। এর প্রভাবটি হ'ল একটি শীর্ষতম উইন্ডোটি খোলার পরে এবং এটি বন্ধ করার পরে, উইন্ডোজ আপনার অ্যাপ্লিকেশনটির অন্যান্য উইন্ডোজটিকে পটভূমিতে সরিয়ে দেয়। এটি অবশ্যই আপনার আবেদনের জন্য পছন্দসই আচরণ নয়। মাইক্রোসফ্ট এটি বাস্তবায়িত করেছিল কারণ অতীতে অনেক প্রোগ্রামাররা খুব হস্তক্ষেপকারী শীর্ষস্থানীয়কে আপত্তি জানায়। শীর্ষস্থানীয় খুব আক্রমণাত্মক। আমি কখনই এটি ব্যবহার করি না।
এলমিউ

9

অ্যালেক্স লিম্যান / থসফটওয়্যারজেদীর উত্তরগুলিতে পিনভোক নেট.এর থেকে প্রাপ্ত নমুনা কোডটি উইন্ডোটিকে একটি "শীর্ষস্থানীয়" উইন্ডোতে পরিণত করবে, এর অর্থ এটি পপ আপ হওয়ার পরে আপনি এটিকে সাধারণ উইন্ডোজের পিছনে রাখতে পারবেন না। তিনি এটি কীসের জন্য ব্যবহার করতে চান তার মাতিয়াসের বিবরণ দেওয়া, এটি সে যা চায় তা হতে পারে। তবে আপনি যদি চান যে ব্যবহারকারী আপনার উইন্ডোটি পপ আপ করার পরে অন্য উইন্ডোগুলির পিছনে রাখতে সক্ষম হয়, কেবলমাত্র নমুনায় HWND_TOPMOST (-1) এর পরিবর্তে HWND_TOP (0) ব্যবহার করুন।


6

ডাব্লুপিএফ এ আপনি এটির মতো সমাধান করতে পারেন:

উইন্ডোতে এই বৈশিষ্ট্যগুলি রাখুন:

<Window
    x:Class="myApplication.winNotification"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  Title="Notification Popup" Width="300" SizeToContent="Height"
  WindowStyle="None" AllowsTransparency="True" Background="Transparent" ShowInTaskbar="False" Topmost="True" Focusable="False" ShowActivated="False" >
</Window>

শেষটির একটি বৈশিষ্ট্য হ'ল আপনার শোঅ্যাক্টিভেটেড = "মিথ্যা" দরকার।


4

আমার অনুরূপ কিছু রয়েছে এবং আমি কেবল বিজ্ঞপ্তি ফর্মটি দেখি এবং তারপরেও করি

this.Focus();

মূল ফর্ম ফোকাস ফিরে আনতে।


সহজ কিন্তু কার্যকর!
টম

3

পৃথক থ্রেডে বিজ্ঞপ্তি ফর্ম তৈরি করুন এবং শুরু করুন এবং ফর্মটি খোলার পরে ফোকাসটি আপনার মূল ফর্মটিতে পুনরায় সেট করুন। বিজ্ঞপ্তি ফর্মটি ইভেন্ট থেকে বরখাস্ত করা একটি অনফর্মঅ্যাপড Form.Shownইভেন্ট সরবরাহ করুন। এটার মতো কিছু:

private void StartNotfication()
{
  Thread th = new Thread(new ThreadStart(delegate
  {
    NotificationForm frm = new NotificationForm();
    frm.OnFormOpen += NotificationOpened;
    frm.ShowDialog();
  }));
  th.Name = "NotificationForm";
  th.Start();
} 

private void NotificationOpened()
{
   this.Focus(); // Put focus back on the original calling Form
}

আপনি আপনার নোটফিকেশনফর্ম অবজেক্টের আশেপাশে একটি হ্যান্ডেল রাখতে পারেন যাতে এটি মূল ফর্ম ( frm.Close()) দ্বারা প্রোগ্রামগতভাবে বন্ধ হয়ে যায় ।

কিছু বিশদ অনুপস্থিত, তবে আশা করি এটি আপনাকে সঠিক পথে চালিত করবে।


এটি কেবল তখনই কাজ করবে যদি আপনার ফর্মটি মূলত সক্রিয় ফর্ম ছিল। এই জাতীয় বিজ্ঞপ্তির মূল উদ্দেশ্যটির বিরুদ্ধে যায় না kind
অ্যালেক্স লাইম্যান

1
তাই না? এটি বিজ্ঞপ্তির উদ্দেশ্য - এটি রাখা এবং মূল সক্রিয় ফর্মটিতে ফোকাস ফিরে পাওয়া।
বব ন্যাডলার

2
এটি কেবলমাত্র আপনার অ্যাপ্লিকেশনের একটি ফর্মকে ফোকাস দেয় - সেই সময়ে যদি অন্য কোনও প্রোগ্রাম সক্রিয় থাকে তবে কী হবে? একটি বিজ্ঞপ্তি উইন্ডো প্রদর্শন করা (সাধারণত ব্যবহারকারীকে আপনার অ্যাপ্লিকেশনটির স্থিতিতে আপডেট দিতে) কেবলমাত্র তখনই কার্যকর যখন তারা আপনার অ্যাপ্লিকেশনটি দেখছেন না।
অ্যালেক্স লাইম্যান

3

আপনি কী ধরণের বিজ্ঞপ্তি প্রদর্শন করতে চান তা বিবেচনা করতে চাইতে পারেন।

যদি মেসেজবক্স ব্যবহার করে কোনও ইভেন্ট সম্পর্কে ব্যবহারকারীকে অবহিত করা একেবারে সমালোচিত হয় other তবে এটি ব্যবহারকারীর নিশ্চিত না হওয়া অবধি মূল উইন্ডোতে অন্য কোনও ইভেন্ট অবরুদ্ধ করার প্রকৃতির কারণে এটি প্রস্তাবিত উপায়। যদিও পপ-আপ অন্ধত্ব সম্পর্কে সচেতন হন।

যদি এটি সমালোচনামূলক থেকে কম হয় তবে আপনি বিজ্ঞপ্তিগুলি প্রদর্শনের বিকল্প উপায় ব্যবহার করতে পারেন, যেমন উইন্ডোর নীচে একটি সরঞ্জামদণ্ড। আপনি লিখেছেন, আপনি পর্দার নীচে ডানদিকে বিজ্ঞপ্তি প্রদর্শন করেন - এটি করার মানক উপায়টি হ'ল সিস্টেম ট্রে আইকনটির সংমিশ্রণে একটি বেলুন টিপ ব্যবহার করা হবে ।


2
- বেলুন টিপস কোনও বিকল্প নয় কারণ অক্ষম করা যেতে পারে - আপনি যদি প্রোগ্রামটি যেভাবেই হ্রাস করতে পারেন তবে স্ট্যাটাস বারটি লুকানো যেতে পারে
ম্যাটাস

3

এটি ভাল কাজ করে।

দেখুন: ওপেন আইকন - এমএসডিএন এবং সেটফোরগ্রাউন্ড উইন্ডো - এমএসডিএন

using System.Runtime.InteropServices;

[DllImport("user32.dll")]
static extern bool OpenIcon(IntPtr hWnd);

[DllImport("user32.dll")]
static extern bool SetForegroundWindow(IntPtr hWnd);

public static void ActivateInstance()
{
    IntPtr hWnd = IntPtr hWnd = Process.GetCurrentProcess().MainWindowHandle;

    // Restore the program.
    bool result = OpenIcon(hWnd); 
    // Activate the application.
    result = SetForegroundWindow(hWnd);

    // End the current instance of the application.
    //System.Environment.Exit(0);    
}

1

আপনি পারেন এটিকে একা যুক্তি দিয়ে পরিচালনা , যদিও আমাকে স্বীকার করতে হবে যে উপরে যেখানে পরামর্শ দেওয়া হয় আপনি চুরি করা ফোকাস ছাড়াই একটি MakeToFront পদ্ধতিতে শেষ করেন যেখানে সবচেয়ে পরামর্শ দেওয়া হয়।

যাইহোক, আমি এটিতে ছুটে এসেছি এবং ডেটটাইম সম্পত্তি ব্যবহার করে এটি সমাধান করেছি যাতে ইতিমধ্যে কলগুলি করা হয়েছিল যদি আর ক্রেডিটফ্রন্ট কলগুলিতে আর অনুমতি না দেয়।

একটি মূল শ্রেণি ধরুন, 'কোর', যা উদাহরণস্বরূপ তিনটি ফর্ম, 'ফর্ম 1, 2, এবং 3' পরিচালনা করে। প্রতিটি ফর্মের একটি ডেটটাইম সম্পত্তি এবং একটি অ্যাক্টিভেট ইভেন্ট দরকার যা উইন্ডোজ সামনে আনার জন্য কোরকে কল করে:

internal static DateTime LastBringToFrontTime { get; set; }

private void Form1_Activated(object sender, EventArgs e)
{
    var eventTime = DateTime.Now;
    if ((eventTime - LastBringToFrontTime).TotalMilliseconds > 500)
        Core.BringAllToFront(this);
    LastBringToFrontTime = eventTime;
}

এবং তারপরে কোর ক্লাসে কাজটি তৈরি করুন:

internal static void BringAllToFront(Form inForm)
{
    Form1.BringToFront();
    Form2.BringToFront();
    Form3.BringToFront();
    inForm.Focus();
}

সাইড নোটে, যদি আপনি একটি ছোট্ট উইন্ডোটিকে তার মূল অবস্থায় পুনরুদ্ধার করতে চান (সর্বাধিক নয়) তবে ব্যবহার করুন:

inForm.WindowState = FormWindowState.Normal;

আবার, আমি জানি এটি একটি ব্রিওটোফ্রন্টউইথআউটফোকসের অভাবে প্যাচ সমাধান solution আপনি যদি ডিএলএল ফাইল এড়াতে চান তবে এটি একটি পরামর্শ হিসাবে বোঝানো হয়েছে।


1

আমি জানি না এটিকে নেকো-পোস্টিং হিসাবে বিবেচনা করা হয় তবে আমি এটিই করেছি যেহেতু আমি এটি ব্যবহারকারীর "শো উইন্ডো" এবং "সেটওয়াইন্ডোপোস" পদ্ধতিতে কাজ করতে পারি না। এবং না, "উইন্ডো অ্যাক্টিভেশন" ওভাররাইড করা এই ক্ষেত্রে কাজ করে না কারণ নতুন উইন্ডোটি সর্বদা শীর্ষে থাকা উচিত। যাইহোক, আমি একটি সহায়ক পদ্ধতি তৈরি করেছি যা পরামিতি হিসাবে ফর্ম নেয়; যখন ডাকা হয়, এটি ফর্মটি দেখায়, সামনে এনে তোলে এবং বর্তমান উইন্ডোটির ফোকাসটি চুরি না করে টপমস্ট করে তোলে (দৃশ্যত এটি করে তবে ব্যবহারকারী লক্ষ্য করবে না)।

    [DllImport("user32.dll")]
    static extern IntPtr GetForegroundWindow();

    [DllImport("user32.dll")]
    static extern IntPtr SetForegroundWindow(IntPtr hWnd);

    public static void ShowTopmostNoFocus(Form f)
    {
        IntPtr activeWin = GetForegroundWindow();

        f.Show();
        f.BringToFront();
        f.TopMost = true;

        if (activeWin.ToInt32() > 0)
        {
            SetForegroundWindow(activeWin);
        }
    }

0

আমি জানি এটি বোকা লাগতে পারে তবে এটি কার্যকর:

this.TopMost = true;
this.TopMost = false;
this.TopMost = true;
this.SendToBack();

যদি আপনি সামনের উইন্ডোটি পিছনে প্রেরণ করেন তবে ব্যাকগ্রাউন্ড উইন্ডোজগুলি নতুন অগ্রভাগটিকে ওভারল্যাপ করে যদি এটি আর প্রদর্শিত না হয়।
তমুসজেরোয়েস

0

আমার উইন্ডো টপমস্ট দিয়ে এটি করা দরকার। আমি উপরের পিনভোক পদ্ধতিটি বাস্তবায়ন করেছি কিন্তু দেখতে পেয়েছি যে আমার লোড ইভেন্টটি উপরে তালার মতো ডাকছে না। আমি অবশেষে সফল। সম্ভবত এটি কাউকে সাহায্য করবে। এখানে আমার সমাধান:

        form.Visible = false;
        form.TopMost = false;
        ShowWindow(form.Handle, ShowNoActivate);
        SetWindowPos(form.Handle, HWND_TOPMOST,
            form.Left, form.Top, form.Width, form.Height,
            NoActivate);
        form.Visible = true;    //So that Load event happens

-4

আপনি যখন একটি নতুন ফর্ম ব্যবহার করে তৈরি করবেন

Form f = new Form();
f.ShowDialog();

এটি ফোকাস চুরি করে কারণ এই কোডটি ফর্মটি বন্ধ না হওয়া পর্যন্ত আপনার কোড মূল ফর্মটিতে চালানো চালিয়ে যেতে পারে না।

ব্যতিক্রমটি হ'ল একটি নতুন ফর্ম তৈরি করতে থ্রেডিং ব্যবহার করে ফর্ম.শো () h থ্রেডটি বিশ্বব্যাপী দৃশ্যমান কিনা তা নিশ্চিত করুন, কারণ যদি আপনি কোনও ফাংশনটির মধ্যে এটি ঘোষণা করেন, আপনার ফাংশনটি বেরোনামাত্র আপনার থ্রেডটি শেষ হয়ে যাবে এবং ফর্মটি অদৃশ্য হয়ে যাবে।


আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.