Trang 1 trên tổng số 8 123... Cuối cùngCuối cùng
Từ 1 tới 10 trên tổng số 72 kết quả

Đề tài: Xác định màn hình ngoài (extended monitor) trong ứng dụng c#

  1. #1
    Ngày gia nhập
    08 2017
    Bài viết
    1,658

    Mặc định Xác định màn hình ngoài (extended monitor) trong ứng dụng c#

    Có những CT cần xuất thông tin ra màn hình ngoài.

    Làm sao xác định đâu là màn hình ngoài (Screen) cần xuất thông tin ra đó ?

  2. #2
    Ngày gia nhập
    02 2014
    Nơi ở
    TP.HCM
    Bài viết
    857

    Trong .NET tôi chưa tìm thấy class nào phù hợp với yêu cầu trên. Tuy nhiên có thể lấy từ C++ thì cũng đơn giản.
    Chương trình bên dưới dùng PInvoice để thực hiện, trên form có 1 button, khi nhấn button thì xuất 1 dòng chữ "CongdongCViet.com" ra góc trên phải màn hình với màu đỏ trên nền xanh
    Visual C# Code:
    1. using System;
    2. using System.Drawing;
    3. using System.Text;
    4. using System.Windows.Forms;
    5. using System.Runtime.InteropServices;
    6.  
    7. namespace WindowsFormsApplication1
    8. {
    9.     public partial class Form1 : Form
    10.     {
    11.         public Form1()
    12.         {
    13.             InitializeComponent();
    14.         }
    15.         private void button1_Click(object sender, EventArgs e)
    16.         {
    17.             Win32.RECT r = new Win32.RECT(Screen.PrimaryScreen.WorkingArea);    // Vùng hiển thị là góc trên phải màn hình
    18.             r.Right -= 20;
    19.             r.Left = r.Right - 140;
    20.             r.Bottom = r.Top + 25;
    21.  
    22.             StringBuilder lpchText = new StringBuilder("CongdongCViet.com");    // Chuỗi hiển thị
    23.  
    24.             IntPtr hdc = Win32.GetDC(IntPtr.Zero);
    25.             Win32.SetTextColor(hdc, 0x00FF);                                    // Màu chữ đỏ
    26.             Win32.SetBkColor(hdc, 0xFFFF00);                                    // Màu nền xanh da trời
    27.            
    28.             Win32.DrawText(hdc, lpchText, -1, ref r, Win32.DT_VCENTER | Win32.DT_SINGLELINE);
    29.             Win32.ReleaseDC(IntPtr.Zero, hdc);
    30.         }
    31.     }
    32.     public class Win32
    33.     {
    34.         [StructLayout(LayoutKind.Sequential)]
    35.         public struct RECT
    36.         {
    37.             public int Left, Top, Right, Bottom;
    38.             public RECT(int left, int top, int right, int bottom)
    39.             {
    40.                 Left = left;
    41.                 Top = top;
    42.                 Right = right;
    43.                 Bottom = bottom;
    44.             }
    45.             public RECT(Rectangle r) : this(r.Left, r.Top, r.Right, r.Bottom) { }
    46.             public int X
    47.             {
    48.                 get { return Left; }
    49.                 set { Right -= (Left - value); Left = value; }
    50.             }
    51.             public int Y
    52.             {
    53.                 get { return Top; }
    54.                 set { Bottom -= (Top - value); Top = value; }
    55.             }
    56.             public int Height
    57.             {
    58.                 get { return Bottom - Top; }
    59.                 set { Bottom = value + Top; }
    60.             }
    61.             public int Width
    62.             {
    63.                 get { return Right - Left; }
    64.                 set { Right = value + Left; }
    65.             }
    66.             public System.Drawing.Point Location
    67.             {
    68.                 get { return new System.Drawing.Point(Left, Top); }
    69.                 set { X = value.X; Y = value.Y; }
    70.             }
    71.             public System.Drawing.Size Size
    72.             {
    73.                 get { return new System.Drawing.Size(Width, Height); }
    74.                 set { Width = value.Width; Height = value.Height; }
    75.             }
    76.             public static implicit operator System.Drawing.Rectangle(RECT r)
    77.             {
    78.                 return new System.Drawing.Rectangle(r.Left, r.Top, r.Width, r.Height);
    79.             }
    80.             public static implicit operator RECT(System.Drawing.Rectangle r)
    81.             {
    82.                 return new RECT(r);
    83.             }
    84.             public static bool operator ==(RECT r1, RECT r2)
    85.             {
    86.                 return r1.Equals(r2);
    87.             }
    88.             public static bool operator !=(RECT r1, RECT r2)
    89.             {
    90.                 return !r1.Equals(r2);
    91.             }
    92.             public bool Equals(RECT r)
    93.             {
    94.                 return r.Left == Left && r.Top == Top && r.Right == Right && r.Bottom == Bottom;
    95.             }
    96.             public override bool Equals(object obj)
    97.             {
    98.                 if (obj is RECT)
    99.                     return Equals((RECT)obj);
    100.                 else if (obj is System.Drawing.Rectangle)
    101.                     return Equals(new RECT((System.Drawing.Rectangle)obj));
    102.                 return false;
    103.             }
    104.             public override int GetHashCode()
    105.             {
    106.                 return ((System.Drawing.Rectangle)this).GetHashCode();
    107.             }
    108.             public override string ToString()
    109.             {
    110.                 return string.Format(System.Globalization.CultureInfo.CurrentCulture, "{{Left={0},Top={1},Right={2},Bottom={3}}}", Left, Top, Right, Bottom);
    111.             }
    112.         }
    113.  
    114.         public const int DT_VCENTER = 0x00000004;
    115.         public const int DT_SINGLELINE = 0x00000020;
    116.  
    117.         [DllImport("user32.dll")]
    118.         public static extern int DrawText(IntPtr hdc, StringBuilder lpchText, int cchText, ref RECT lprc, uint dwDTFormat);
    119.  
    120.         [DllImport("user32.dll")]
    121.         public static extern IntPtr GetDC(IntPtr hWnd);
    122.  
    123.         [DllImport("user32.dll")]
    124.         public static extern IntPtr ReleaseDC(IntPtr hWnd, IntPtr hdc);
    125.  
    126.         [DllImport("gdi32.dll")]
    127.         public static extern uint SetTextColor(IntPtr hdc, int crColor);
    128.  
    129.         [DllImport("gdi32.dll")]
    130.         public static extern uint SetBkColor(IntPtr hdc, int crColor);
    131.     }
    132. }

  3. #3
    Ngày gia nhập
    08 2017
    Bài viết
    1,658

    Với


    Chương trình bạn viết: nó xuất ra màn hình 1, không như mong muốn, xuất ra màn hình 2

    Xuất ra ở đây có thể là form.

  4. #4
    Ngày gia nhập
    02 2014
    Nơi ở
    TP.HCM
    Bài viết
    857

    Nhu cầu của bạn rất cao, bản thân tôi thì còn rất yếu với lập trình trên C# nên khó diễn đạt hết ý được.
    Nếu bạn có hứng thú với lập trình cho Multi-Monitors, tôi đề xuất chúng ta thảo luận trên C\C++ với Windows API.
    Nếu bạn đồng ý , một vài ngày sau tôi sẽ tạo đề tài mới,

  5. #5
    Ngày gia nhập
    08 2017
    Bài viết
    1,658

    Viết bằng NNLT nào cũng được, không nhất thiết phải là c#.

    Nó khá phức tạp bởi các tổ hợp có thể có, ở bên trái (hay bên phải so sánh hình trên), là main display, sai lệch tọa độ, ...


    Với phương án bán thủ công, có can thiệp của con người:
    Visual C# Code:
    1.         private void itmScreen1_Click(object sender, EventArgs e) {
    2.             Screen[] sc = Screen.AllScreens;
    3.             Rectangle rc = sc[0].Bounds;
    4.             showOnMonitor(rc.Left, rc.Top);
    5.         }
    6.         private void itmScreen2_Click(object sender, EventArgs e) {
    7.             Screen[] sc = Screen.AllScreens;
    8.             if (sc.Length < 2) return;
    9.             Rectangle rc = sc[sc.Length - 1].Bounds;
    10.             showOnMonitor(rc.Left, rc.Top);
    11.         }
    12. //
    13.         void showOnMonitor(int xPos, int yPos) {
    14.             this.Location = new Point(xPos, yPos);
    15.             this.StartPosition = FormStartPosition.Manual;
    16.             this.WindowState = FormWindowState.Normal;
    17.             this.WindowState = FormWindowState.Maximized;
    18.         }

  6. #6
    Ngày gia nhập
    02 2014
    Nơi ở
    TP.HCM
    Bài viết
    857

    Mặc định Xác định màn hình ngoài (extended monitor) trong ứng dụng c#

    Với phương án này có thể bạn không xuất dữ liệu ra Screen được (tức là phần màn hình Screen[x] nằm bên ngoài các form). Điều thứ 2 là bạn cũng khó mà xuất liệu (ghi đè) lên các form (cửa sổ) không phải từ thể hiện chương trình bạn ? Theo mã trên thì chắc bạn muốn dùng xảo thuật xuất trên form (form chiếm giữ hoàn toàn vùng màn hình tổng) - chứ thực chất không xuất trên màn hình. Tôi cũng sẽ thử theo phương pháp của bạn, có gì thảo luận tiếp.

  7. #7
    Ngày gia nhập
    08 2017
    Bài viết
    1,658

    #5 là CT thật, nó làm việc đúng yêu cầu, chỉ thiếu detect trực tiếp bằng code để xuất ra screen 2, thông qua switch bởi nhân viên vận hành.

    Trên cũng không có xảo thuật, nó cần xuất với kích thước lớn nhất (FormWindowState.Maximized
    Muốn ShowOnTop(ghi đè thì không khó. nó chỉ là prop thiết lập nó dễ dàng.

  8. #8
    Ngày gia nhập
    02 2014
    Nơi ở
    TP.HCM
    Bài viết
    857

    Tôi gợi ý bạn dùng các hàm Windows API như : EnumDisplayMonitors và MonitorEnumProc có thể mềm dẻo hơn và có thể ghi trực tiếp ra Monitor mà không phải mượn tạm bề mặt của form.

  9. #9
    Ngày gia nhập
    02 2014
    Nơi ở
    TP.HCM
    Bài viết
    857

    Môt chương trình nhỏ viết bằng API, bạn xem thêm (tuy không đúng chỗ nhưng tôi không muốn tạo luồng mới).
    Visual C++ Code:
    1. #include<Windows.h>
    2. #include"resource.h"
    3.  
    4. class CMyDialog
    5. {
    6. private:
    7.     HWND        m_hDlg;     // Thẻ cửa sổ hộp thoại
    8.     int         m_cCount;   // Số Monitors
    9.  
    10.     static BOOL CALLBACK MonitorEnumProc(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData)
    11.     {
    12.         CMyDialog * pMyDialog = (CMyDialog *)dwData;
    13.         pMyDialog->ShowText(hdcMonitor, lprcMonitor);
    14.         pMyDialog->m_cCount++;
    15.         return TRUE;
    16.     }
    17.     void ShowText(HDC hdc, LPRECT pRect)
    18.     {
    19.         SetTextColor(hdc, RGB(255, 0, 0));
    20.         SetBkColor(hdc, RGB(0, 255, 255));
    21.         CHAR    szText[] = "CongDongCViet.com";
    22.         TextOut(hdc, pRect->right - 200, pRect->top + 10, szText, lstrlen(szText));
    23.     }
    24.  
    25.     static BOOL CALLBACK DialogProc(HWND hDlg, UINT message, WPARAM wparam, LPARAM lparam)
    26.     {
    27.         if (message == WM_INITDIALOG)
    28.         {
    29.             CMyDialog * pMyDialog = reinterpret_cast<CMyDialog *>(lparam);
    30.             SetWindowLongPtr(hDlg, GWLP_USERDATA, PtrToUlong(pMyDialog));
    31.             return pMyDialog->OnInitDialog(hDlg);
    32.         }
    33.         CMyDialog * pMyDialog = reinterpret_cast<CMyDialog *>(static_cast<LONG_PTR>(GetWindowLongPtr(hDlg, GWLP_USERDATA)));
    34.         switch (message)
    35.         {
    36.         case WM_COMMAND:    return pMyDialog->OnCommand(wparam);
    37.         case WM_CLOSE:      return pMyDialog->OnClose();
    38.         }
    39.         return FALSE;
    40.     }
    41.     BOOL OnInitDialog(HWND hDlg)
    42.     {
    43.         m_hDlg = hDlg;
    44.         return TRUE;
    45.     }
    46.     BOOL OnCommand(WPARAM wparam)
    47.     {
    48.         switch (LOWORD(wparam))
    49.         {
    50.         case IDC_BUTTON1:
    51.             Button1_Click();
    52.             return TRUE;
    53.         case IDOK:
    54.         case IDCANCEL:
    55.             return OnClose();
    56.         }
    57.         return FALSE;
    58.     }
    59.     BOOL OnClose()
    60.     {
    61.         EndDialog(m_hDlg, 0);
    62.         return TRUE;
    63.     }
    64.  
    65.     void Button1_Click()
    66.     {
    67.         HDC     hdc = GetDC(NULL);
    68.         m_cCount = 0;
    69.         hdc = GetDC(NULL);
    70.         EnumDisplayMonitors(hdc, NULL, MonitorEnumProc, (LPARAM)this);
    71.         ReleaseDC(NULL, hdc);
    72.         CHAR    szMess[MAX_PATH];
    73.         wsprintf(szMess, "NumMonitors = %d", m_cCount);
    74.         MessageBox(m_hDlg, szMess, "", 0);
    75.     }
    76.  
    77. public:
    78.     void Show(HINSTANCE hInst)
    79.     {
    80.         DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_DIALOG1), NULL, DialogProc, (LPARAM)this);
    81.     }
    82. };
    83.  
    84. int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrev, LPSTR lpCmd, int nShow)
    85. {
    86.     CMyDialog   myDlg;
    87.     myDlg.Show(hInstance);
    88.     return 0;
    89. }
    Attached Files Attached Files

  10. #10
    Ngày gia nhập
    08 2017
    Bài viết
    1,658

    Viết bằng NNLT nào, ở box nào theo tôi không quan trọng lắm.
    Về mặt ứng dụng, nó khá phổ biến, ví dụ :
    - hội đồng kiểm phiếu cần xuất tiến trình ra monitor cho công chúng xem,
    - tại các ga chờ thông báo, giờ chuyến, vị trí cho khách hàng biết,
    - các chương trình dạy tại các trường, ...

    Khi hệ thống ổn định thì các ứng dụng của hệ điều hành (HDH) cũng nhớ được vị trí, kích thước, Screen của chúng trong phiên làm việc trước đó. Chúng có thể lưu vào file cấu hình, registry (những dạng database của riêng chúng)

    Vấn đề ở đây là khi xảy ra sự cố bất thường, làm sao xác định hệ thống có đúng theo yêu cầu của CT cần làm việc : đâu là màn hình ngoài (Screen) cần xuất thông tin ra đó ?

Quyền hạn của bạn

  • Bạn không thể gửi đề tài mới
  • Bạn không thể gửi bài trả lời
  • Bạn không thể gửi các đính kèm
  • Bạn không thể chỉnh sửa bài viết của bạn