Chào các bạn,

Trước tiên, mình không rành, đúng hơn là không biết gì về lập trình Win32, tức là sử dụng C++ thuần túy + Windows API á. Mình chỉ biết đến C++.NET hà , nên không viết được ứng dụng để đáp ứng nhu cầu


Sau đây là một ứng dụng nhỏ xíu, được mình viết bằng C++/CLI có sử dụng API của Windows.

Mục đích của chương trình : Gởi một/vài ký tự bàn phím đến một cửa sổ đang mở
(vd: Notepad).
Trình biên dịch : Visual Studio 2k5
Ngôn ngữ : C++/CLI (Windows Form) .NET 2.0
Hệ điều hành : WinXP
Giao diện chương trình: Chỉ là 1 DialogBox , trên dialog có:
- 1 text box tên : txtBoxWindowTitle. Lấy vào tên hay tiêu đề (title) của cửa sổ sẽ nhận ký tự bàn phím .
- 1 text box tên : txtBoxKeys. Lấy các ký tự người dùng nhập vào (để gởi sang cửa sổ txtBoxWindowTitle).
- một nút nhấn (button1). Khi nhấn nút này thì các ký tự có trong txtBoxKeys sẽ gởi sang cửa sổ có tiêu đề txtBoxWindowTitle.

Các dòng mã chính của chương trình :
Visual C# Code:
  1. namespace SendKeys
  2. {
  3.     using namespace System;
  4.     using namespace System::ComponentModel;
  5.     ….
  6.     using name System::Runtime::InteropServices;
  7.  
  8.         [DllImport("user32.dll", SetLastError= true)]
  9.     IntPtr FindWindow(String^ className, String^ windowName );
  10.     [DllImport("user32.dll", SetLastError= true)]
  11.     bool SetForegroundWindow(IntPtr hWnd);
  12.  
  13. public ref class Form1 : public System::Windows::Forms::Form
  14.     {
  15.     ...
  16.     private: System::Windows::Forms::TextBox^  txtBoxWindowTitile;
  17.     private: System::Windows::Forms::TextBox^  txtBoxKeys;
  18.     private: System::Windows::Forms::Button^  button1;
  19.  
  20. ...
  21.  
  22.  
  23.  
  24.  
  25.  
  26.  
  27.     private: System::Void button1_Click(System::Object^  sender,
  28. System::EventArgs^  e)
  29.     {
  30.         IntPtr hWnd = FindWindow(nullptr,   // Lay handle cua cua so
  31.             txtBoxWindowTitile->Text );           // tu text box.
  32.             SetForegroundWindow(hWnd);        // Lam cho cua so lay
  33.                                                             // duoc noi len tren cung  
  34.             SendKeys::Send(txtBoxKeys->Text); // Goi cac ky tu lay duoc
  35.                                                               // tu text box                           
  36.      }
  37. }; // Form1
  38. }// SendKeys

Chương trình này chạy tốt . Chẳng có vấn đề gì cả. Nhưng mình thấy không hài lòng lắm, bở vì khi dùng hàm SetForegroundWindow(); cái cửa sổ nhận phím nổi lên trên cùng, khi đó mình không thể thao tác được với cửa sổ chính của chương trình.

Các bạn có cách nào gởi phím vào một chương trình mà không làm nó “nổi lên” hay không vậy vậy ?

Mình thấy có một vài chương trình, vd như các chương trình auto play game vltk ( các auto play hồi đâu tiên hết á) nó gởi phím vào một cửa sổ nhưng không làm nó nổi lên. Mình có tìm hiểu thì thấy nó nói tới việc dùng cơ chế Windows hook hoặc API hook gì đó. Khó khăn nằm chỗ này, một DLL của .NET không thể load vào process của một chương trình không phải .NET . Việc này mình có thể nhờ một người bạn viết dùm, coi như cái DLL không thành vấn đề nữa. Nhưng cái chương trình chính của mình vẫn dùng C++/CLI .NET, vẫn dùng kỹ thuật P/Invoke để sử dụng các API của Windows Windows nhằm mục đích inject cái DLL vào process của chương trình khác. Và khó khăn của mình đây.

Một số API của Window, vd :

Visual C++ Code:
  1. HANDLE WINAPI OpenProcess(
  2.   DWORD dwDesiredAccess,
  3.   BOOL bInheritHandle,
  4.   DWORD dwProcessId
  5. );
  6.  
  7. LPVOID VirtualAllocEx(
  8.   HANDLE hProcess,
  9.   LPVOID lpAddress,
  10.   SIZE_T dwSize,
  11.   DWORD flAllocationType,
  12.   DWORD flProtect
  13. );
  14.  
  15. BOOL WriteProcessMemory(
  16.   HANDLE hProcess,
  17.   LPVOID lpBaseAddress,
  18.   LPCVOID lpBuffer,
  19.   SIZE_T nSize,
  20.   SIZE_T* lpNumberOfBytesWritten
  21. );


Hàm này có các kiểu mà mình chưa biết đến bao giờ cả (SIZE_T, LPVOID, LPCVOID, DWORD), nên không biết nó tương ứng với các kiểu nào trong C++/CLI. Mình chỉ mới biết được mỗi một loại kiểu dạng handle (HANDLE, , HINSTANCE, and HHOOK) là tương ứng với kiểu IntPtr của C++/CLI à. Tới chỗ này thì mình bị bí lù rồi, không tiếp tục được công việc. Nếu bạn nào biết thì chỉ cách mình tìm hiểu về các kiểu được các API của Windows sử dụng để mình có thể sử dụng được các API này. Khi đó mình mới có thể inject cái DLL vào process của một chương trình khác và giao tiếp với ứng dụng của mình được.


Cám ơn các bạn đã đọc tin.