Program Tangkapan Layar menyalin lebih dari area yang dipilih

Saya mengikuti program Huw Collingbourne dalam membuat program tangkapan layar dengan C#. Namun, saya memperhatikan beberapa item aneh, dan apakah saya menggunakan program yang dibuatnya atau program yang saya modifikasi melakukan hal yang sama. Secara khusus saya membuat program yang membuka jendela yang memungkinkan Anda menangkap area tersebut. Saya pikir ini ada hubungannya dengan duduk di komputer saya, tetapi perlu tahu bagaimana mengantisipasi dan memperbaikinya jika orang lain akan menggunakan program tangkapan layar saya! Jika tampilan saya untuk windows 10 diatur ke 100% saya mendapatkan sedikit lebih banyak daripada jendela yang dipilih dan jika saya mengatur tampilan ke 125% teks maka saya mendapatkan banyak area yang dipilih. Membiarkan ukuran default saya seharusnya berukuran 555, 484. tapi saya menangkap jauh lebih besar.

public partial class Form1 : Form
{
    //https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-getwindowrect
    [DllImport("user32.dll")]
    private static extern IntPtr GetForegroundWindow();
    [DllImport("user32.dll")]
    private static extern IntPtr GetDesktopWindow();
    [DllImport("user32.dll")]
    private static extern bool GetWindowRect(IntPtr hWnd, ref Rectangle lpRect);

    //ICON info
    //https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-getcursorinfo
    [DllImport("user32.dll")]
    private static extern bool GetIconInfo(IntPtr hIcon, out ICONINFO piconinfo);
    [DllImport("user32.dll")]
    private static extern bool GetCursorInfo(out CURSORINFO pci);


    public struct POINT
    {
        public Int32 x;
        public Int32 y;
    }

    public struct ICONINFO
    {
        public bool fIcon;
        public Int32 xHotspot;
        public Int32 yHotspot;
        public IntPtr hbmMask;
        public IntPtr hbmColor;
    }

    public struct CURSORINFO
    {
        public Int32 cbSize;
        public Int32 flags;
        public IntPtr hCursor;
        public Point ptScreenPos;
    }

    GrabRegionForm grabForm;

    public void GrabRect(Rectangle rect)
    {
        int rectWidth = rect.Width - rect.Left;
        int rectHeight = rect.Height - rect.Top;
        Bitmap bm = new Bitmap(rectWidth, rectHeight);
        Graphics g = Graphics.FromImage(bm);
        g.CopyFromScreen(rect.Left, rect.Top, 0, 0, new Size(rectWidth, rectHeight));
        DrawMousePointer(g, Cursor.Position.X - rect.Left, Cursor.Position.Y - rect.Top);
        this.pb_screengrab.Image = bm;
        Clipboard.SetImage(bm);
    }
}

public partial class GrabRegionForm : Form
{
    public Rectangle formRect;
    private Form1 mainForm;
    [DllImport("user32.dll")]
    public static extern bool ReleaseCapture();
    [DllImport("user32.dll")]
    public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
    private void buttonOK_Click(object sender, EventArgs e)
    {
        formRect = new Rectangle(this.Left, this.Top, this.Left + this.Width, this.Top + this.Height);
        this.Hide();
        mainForm.GrabRect(formRect);
        Close();
    }
}

ScreenGrab dengan Tampilan 100%

ScreenGrab dengan Tampilan 125%

Area yang menampilkan jendela pengambilan

Area yang Sebenarnya Ditangkap


person John B    schedule 18.12.2018    source sumber
comment
Lihat catatan di sini: Gambar tidak digambar di tempat yang benar   -  person Jimi    schedule 18.12.2018
comment
Selain itu, jika aplikasi Anda bukan DPIAware, aplikasi tersebut akan mengalami virtualisasi, artinya Sistem akan menskalakannya secara otomatis. Artinya, semua pengukuran terkait layar dan nilai DPI juga divirtualisasi. Jika demikian, lihat di sini: Cara mengonfigurasi aplikasi agar berjalan dengan benar di mesin dengan setelan DPI tinggi. Beberapa catatan yang saya tulis tentang subjek di sini.   -  person Jimi    schedule 18.12.2018
comment
Terima kasih Jimi, itu bekerja dengan sempurna!!!   -  person John B    schedule 21.12.2018
comment
Koreksi. Terima kasih Jimi yang bekerja dengan sempurna untuk Wilayah kedua layar, dan tangkapan layar Tampilan 1. tapi sayangnya tangkapan layar tampilan ke-2 gagal.   -  person John B    schedule 21.12.2018
comment
private void GrabScreen() { Rectangle rect = Screen.AllScreens[Cb_selectedScreen.SelectedIndex].Bounds; Bitmap bm = Bitmap baru(persegi.Lebar, persegi.Tinggi); Grafik g = Grafik.FromImage(bm); g.CopyFromScreen(persegi.X, persegi.Y, 0, 0, persegi.Ukuran); DrawMousePointer(g, Kursor.Posisi.X, Kursor.Posisi.Y); this.pb_screengrab.Image = bm; Papan Klip.SetImage(bm); MakeTopMost(); ToPlayOrNot();   -  person John B    schedule 21.12.2018
comment
Baca catatan ini: Menggunakan SetWindowPos dengan banyak monitor dan baca kembali catatan di tautan pertama. Anda perlu mengatur DPI Bitmap sesuai dengan DPI sumber. Oleh karena itu, Anda memerlukan DPI layar dan menggunakan informasi tersebut untuk mengatur DPI Bitmap Anda. Jika tidak, standar 96 dpi akan digunakan. Di Windows 10, DPI layar default (utama),   -  person Jimi    schedule 21.12.2018
comment
Selain itu, terima kasih Anda juga atas sesuatu yang berfungsi dengan sempurna. Tapi Anda tidak mengatakan apa yang berhasil. Anda memerlukan aplikasi DPIAware dan mengatur Bitmap dengan benar.   -  person Jimi    schedule 21.12.2018
comment
Saya sangat menghargai bantuan Anda. Saya akan memeriksanya. tautan pertama Gambar tidak digambar di tempat yang benar agak membingungkan karena berbicara tentang email dari sebuah file. Sedangkan milik saya adalah screen shotnya. Mencoba mencari cara untuk mengubah tangkapan saya menjadi apa yang Anda miliki, saya menggunakan Bitmap bm = new Bitmap(rect.Width, rect.Height); lalu g.CopyFromScreen(rect.X, rect.Y, 0, 0, rect.Size);. Maaf saya masih pemula dalam hal ini dan grafiknya tampaknya sangat lemah.   -  person John B    schedule 21.12.2018
comment
Pastinya tidak ada email yang disebutkan di tautan pertama :)   -  person Jimi    schedule 21.12.2018
comment
Saat saya mengambil batas layar, ukurannya menjadi 2400x1350, yang aneh karena layar saya berukuran 1920x1080 tanpa perubahan pengaturan DPI. Menggunakan Screen.AllScreens tampaknya mendapatkan batasan yang salah. Saya bahkan mencoba memasukkannya ke dalam Screen.FromRectangle, dan itu gagal karena nomornya salah pada awalnya. Pada dasarnya pada layar utama memberikan area abu-abu di kanan dan bawah, dan pada layar ke-2 di kiri memberikan area abu-abu di kiri dan bawah.   -  person John B    schedule 21.12.2018
comment
Woo hoo!!! Sekarang sudah diperbaiki! Saya harus keluar dan kembali ke windows dengan DPI default. Dari apa yang saya tahu, VS2017 membawa pilihan yang lebih banyak!!! TERIMA KASIH JIMI atas bantuan Anda yang luar biasa!!!!!!   -  person John B    schedule 21.12.2018


Jawaban (1)


JIKA menggunakan lebih lama dari 4.7 dan bukan windows 10 ikuti contoh Jimi dan pastikan Anda keluar dan kembali ke windows.

Dari Jimi https://stackoverflow.com/users/7444103/jimi Cara mengonfigurasi aplikasi agar berjalan dengan benar di mesin dengan pengaturan DPI tinggi Bagaimana cara mengonfigurasi aplikasi agar berjalan dengan benar di mesin dengan setelan DPI tinggi (misalnya 150%)?

Dari Jimi https://stackoverflow.com/users/7444103/jimi Menggunakan SetWindowPos dengan banyak monitor Menggunakan SetWindowPos dengan banyak monitor

Jika saya menargetkan aplikasi saya untuk Windows 10 Saja, sekarang menjadi sangat sederhana. Microsoft semakin memudahkan untuk mengubah pengaturan DPI dengan menggunakan 4.7 jika menggunakan Windows 10.

https://docs.microsoft.com/en-us/dotnet/framework/winforms/high-dpi-support-in-windows-forms

Deklarasikan kompatibilitas dengan Windows 10. Kemudian tambahkan yang berikut ini ke file app.manifest dalam XML di bawah perintah untuk kompatibilitas Windows 10.

supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"

Aktifkan kesadaran DPI per monitor di file app.config. Windows Forms memperkenalkan elemen baru untuk mendukung fitur baru dan penyesuaian yang ditambahkan mulai dengan .NET Framework 4.7. Untuk memanfaatkan fitur baru yang mendukung DPI tinggi, tambahkan yang berikut ini ke file konfigurasi aplikasi Anda.

Buka baris XML untuk System.Windows.Forms.ApplicationConfigurationSection

add key="DpiAwareness" value="PerMonitorV2"
person John B    schedule 11.02.2019