Bagaimanakah saya boleh mendapatkan ID proses atau nama aplikasi yang mengemas kini papan keratan?

王林
Lepaskan: 2024-02-12 13:40:06
ke hadapan
890 orang telah melayarinya

Bagaimanakah saya boleh mendapatkan ID proses atau nama aplikasi yang mengemas kini papan keratan?

Kandungan soalan

Saya sedang mencipta pengurus papan keratan dalam c# dan kadangkala saya menghadapi situasi di mana papan keratan ditetapkan kepada kosong oleh sesetengah aplikasi.

Ini berlaku apabila contohnya excel menyahpilih sesuatu yang baru disalin, jadi saya perlu menentukan sama ada papan keratan itu kosong, tetapi bagaimanakah saya hendak mendapatkan nama aplikasi yang mengemas kini papan keratan?

Saya harap saya boleh mendapatkan hwnd pemegang kepada aplikasi yang mengemas kini papan keratan supaya saya dapat mencari proses di belakangnya menggunakan kod berikut:

[dllimport("user32.dll", setlasterror = true)]
public static extern uint getwindowthreadprocessid(intptr hwnd, out uint lpdwprocessid);
...

protected override void wndproc(ref message m)
{
    switch (m.msg)
    {
        case wm_clipboardupdate:
            // how to get the "handle" hwnd?
            intptr handle = ??? <============= how to get this one ???

            // get the process id from the hwnd
            uint processid = 0;
            getwindowthreadprocessid(handle, out processid);

            // get the process name from the process id
            string processname = process.getprocessbyid((int)processid).processname;

            console.writeline("clipboard update event from [" + processname + "]");
            break;
        }
        default:
            base.wndproc(ref m);
            break;
    }
}
Salin selepas log masuk

Saya harap saya boleh menggunakan message 对象中的 hwnd dalam objek mesej, tetapi ini nampaknya aplikasi saya sendiri - mungkin memberitahu aplikasi dengan id proses ini:

Sekiranya saya boleh mendapatkannya dengan cara lain maka itu juga tidak mengapa, tetapi saya akan menghargai sebarang pandangan tentang ini :-)

Penyelesaian

Berdasarkan jawapan @jimi, ianya mudah. Saya boleh menambah 3 baris berikut pada kod asal saya:

// Import the "GetClipboardOwner" function from the User32 library
[DllImport("user32.dll")]
public static extern IntPtr GetClipboardOwner();
...

// Replace the original line with "HOW TO GET THIS ONE" with this line below - this will give the HWnd handle for the application that has changed the clipboard:
IntPtr handle = GetClipboardOwner();
Salin selepas log masuk

Penyelesaian

Anda boleh menghubungi getclipboardowner()< /a> untuk mendapatkan pemegang tetingkap kali terakhir papan keratan ditetapkan atau dikosongkan (operasi yang mencetuskan pemberitahuan).

[...] Secara umumnya, pemilik papan keratan ialah tetingkap yang terakhir meletakkan data ke dalam papan keratan.
Fungsi papan klip kosong memperuntukkan pemilikan papan keratan.

Dalam beberapa kes khas, satu proses menghantar pemegang kosong kepada openclipboard(): baca bahagian kenyataan fungsi ini dan fungsi emptyclipboard.

Aplikasi mesti membuka papan klip sebelum memanggil papan klip kosong Dengan menggunakan fungsi openclipboard. Jika permohonan menyatakan Pemegang tetingkap adalah batal apabila membuka papan klip, papan klip kosong berjaya Tetapi menetapkan pemilik papan keratan kepada batal. Ambil perhatian bahawa ini mengakibatkan setclipboarddata gagal.

▶ Di sini saya menggunakan kelas terbitan nativewindow< /a> untuk menyediakan pendengar papan keratan. Tetingkap yang mengendalikan mesej kemas kini papan keratan dibuat dengan memulakan objek createparams dan menghantar parameter ini kepada kaedah nativewindow.createhandle(createparams), yang digunakan untuk mencipta tetingkap invisible.
Kemudian tulis semula pemberitahuan wndproc,接收 wm_clipboardupdate nativewindow yang dimulakan.

Fungsi

addclipboardformatlistener digunakan untuk meletakkan tetingkap dalam rantai pendengar papan keratan sistem.

clipboardupdatemonitor 类在收到剪贴板通知时生成一个事件。事件中传递的自定义 clipboardchangedeventargs 对象包含由 getclipboardowner() Pemegang kepada pemilik papan keratan, dikembalikan oleh getwindowthreadprocessid(), dan nama proses, dikembalikan oleh process.getprocessbyid().

Anda boleh menetapkan objek clipboardupdatemonitor seperti ini:
Kelas ini juga boleh dimulakan dalam program.cs

private clipboardupdatemonitor clipboardmonitor = null;
// [...]

clipboardmonitor = new clipboardupdatemonitor();
clipboardmonitor.clipboardchangednotify += this.clipboardchanged;
// [...]

private void clipboardchanged(object sender, clipboardchangedeventargs e)
{
    console.writeline(e.processid);
    console.writeline(e.processname);
    console.writeline(e.threadid);
}
Salin selepas log masuk
using system.diagnostics;
using system.runtime.interopservices;
using system.security.permissions;
using system.windows.forms;

public sealed class clipboardupdatemonitor : idisposable
{
    private bool isdisposed = false;
    private static clipboardwindow window = null;
    public event eventhandler<clipboardchangedeventargs> clipboardchangednotify;

    public clipboardupdatemonitor()
    {
        window = new clipboardwindow();
        if (!nativemethods.addclipboardformatlistener(window.handle)) {
            throw new typeinitializationexception(nameof(clipboardwindow), 
                new exception("clipboardformatlistener could not be initialized"));
        }
        window.clipboardchanged += clipboardchangedevent;
    }

    private void clipboardchangedevent(object sender, clipboardchangedeventargs e) 
        => clipboardchangednotify?.invoke(this, e);

    public void dispose()
    {
        if (!isdisposed) {
            // cannot allow to throw exceptions here: add more checks to verify that 
            // the nativewindow still exists and its handle is a valid handle
            nativemethods.removeclipboardformatlistener(window.handle);
            window?.destroyhandle();
            isdisposed = true;
        }
    }

    ~clipboardupdatemonitor() => dispose();

    private class clipboardwindow : nativewindow
    {
        public event eventhandler<clipboardchangedeventargs> clipboardchanged;
        public clipboardwindow() {
            new securitypermission(securitypermissionflag.unmanagedcode).demand();
            var cp = new createparams();

            cp.caption = "clipboardwindow";
            cp.height = 100;
            cp.width = 100;

            cp.parent = intptr.zero;
            cp.style = nativemethods.ws_clipchildren;
            cp.exstyle = nativemethods.ws_ex_controlparent | nativemethods.ws_ex_toolwindow;
            this.createhandle(cp);
        }
        protected override void wndproc(ref message m)
        {
            switch (m.msg) {
                case nativemethods.wm_clipboardupdate:
                    intptr owner = nativemethods.getclipboardowner();
                    var threadid = nativemethods.getwindowthreadprocessid(owner, out uint processid);
                    string processname = string.empty;
                    if (processid != 0) {
                        using (var proc = process.getprocessbyid((int)processid)) { 
                            processname = proc?.processname;
                        }
                    }
                    clipboardchanged?.invoke(null, new clipboardchangedeventargs(processid, processname, threadid));
                    m.result = intptr.zero;
                    break;
                default:
                    base.wndproc(ref m);
                    break;
            }
        }
    }
}
Salin selepas log masuk

Tersuai eventargs objek yang membawa maklumat terkumpul tentang pemilik papan keratan:

public class clipboardchangedeventargs : eventargs
{
    public clipboardchangedeventargs(uint processid, string processname, uint threadid)
    {
        this.processid = processid;
        this.processname = processname;
        this.threadid = threadid;
    }
    public uint processid { get; }
    public string processname { get; }
    public uint threadid { get; }
}
Salin selepas log masuk

nativemethods Kategori:

internal static class NativeMethods
{
    [DllImport("user32.dll", SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    internal static extern bool AddClipboardFormatListener(IntPtr hwnd);

    [DllImport("user32.dll", SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    internal static extern bool RemoveClipboardFormatListener(IntPtr hwnd);

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

    [DllImport("user32.dll", SetLastError = true)]
    internal static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);

    internal const int WM_CLIPBOARDUPDATE = 0x031D;

    internal const int WS_CLIPCHILDREN = 0x02000000;
    internal const int WS_EX_TOOLWINDOW = 0x00000080;
    internal const int WS_EX_CONTROLPARENT = 0x00010000;
}
Salin selepas log masuk

Atas ialah kandungan terperinci Bagaimanakah saya boleh mendapatkan ID proses atau nama aplikasi yang mengemas kini papan keratan?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

sumber:stackoverflow.com
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan
Tentang kita Penafian Sitemap
Laman web PHP Cina:Latihan PHP dalam talian kebajikan awam,Bantu pelajar PHP berkembang dengan cepat!