I have a Windows Forms Application that imports and uses some C++ methods from user32.dll.
[DllImport("user32.dll")]
public static extern IntPtr WindowFromPoint(int xPoirnt, int yPoint);
[DllImport("user32.dll")]
public static extern IntPtr FindWindow(String sClassName, String sAppName);
[DllImport("user32.dll")]
public static extern IntPtr FindWindowEx(IntPtr parentHandel, IntPtr childAfter, String sClassName, String windowTitle);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
public static extern IntPtr SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
[DllImport("user32.dll")]
public static extern bool PostMessage(IntPtr hWnd, uint Msg, int wParam, int lParam);
[DllImport("user32.dll")]
public static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);
[DllImport("user32.dll")]
public static extern bool PrintWindow(IntPtr hWnd, IntPtr hdcBlt, int nFlags);
[DllImport("msvcrt.dll")]
private static extern int memcmp(IntPtr b1, IntPtr b2, long count);
I've noticed that after my app runs for an extended period of time, the memory usage can go up to 500~MB (initial 5MB).
I don't have that much C++ experience but I know that you have to manually do memory management for C++.
My questions is, do I have to do memory management for my app or will the C# garbage collector handle it.
Related
So I'm trying to make a winapi application by using PInvoke. So far I've been able to open a window, but from there, I can't seem to make the WndProc work. Right now, the application starts, but it won't respond neither to resize, nor to movement or anything, except the hovering above the control buttons.
WindowLL.cs:
public delegate long WndProc(IntPtr hWnd, uint message, byte wParam, long lParam);
public static unsafe class WindowLL
{
[DllImport("user32.dll", CallingConvention = CallingConvention.StdCall, SetLastError = true)]
public static extern ushort RegisterClassExA(ref WNDCLASSEX _class);
[DllImport("user32.dll", CallingConvention = CallingConvention.StdCall, SetLastError = true)]
public static extern IntPtr CreateWindowExA(
uint extraStyle,
ushort className,
//[MarshalAs(UnmanagedType.LPWStr)]
//string className,
[MarshalAs(UnmanagedType.LPStr)]
string title,
uint style,
int x,
int y,
int width,
int height,
IntPtr parent,
IntPtr menu,
IntPtr instance,
IntPtr parameter
);
[DllImport("user32.dll", CallingConvention = CallingConvention.StdCall)]
public static extern bool DestroyWindow(IntPtr hWnd);
[DllImport("user32.dll", CallingConvention = CallingConvention.StdCall, SetLastError = true)]
public static extern bool ShowWindow(IntPtr hWnd, int cmdShow);
[DllImport("user32.dll", CallingConvention = CallingConvention.StdCall)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetMessage(
out MSG lpMsg,
IntPtr hWnd,
uint wMsgFilterMin,
uint wMsgFilterMax
);
[DllImport("user32.dll", CallingConvention = CallingConvention.StdCall)]
public static extern uint DispatchMessage(ref MSG lpMsg);
[DllImport("user32.dll", CallingConvention = CallingConvention.StdCall)]
public static extern uint TranslateMessage(ref MSG lpMsg);
[DllImport("user32.dll", CallingConvention = CallingConvention.StdCall)]
public static extern long DefWindowProcA(
IntPtr hWnd,
uint Msg,
byte wParam,
long lParam
);
}
Structures (split into different files):
[StructLayout(LayoutKind.Sequential)]
public struct MSG
{
public IntPtr hwnd;
public uint message;
public byte wParam;
public long lParam;
public short time;
public POINT pt;
public short lPrivate;
}
[StructLayout(LayoutKind.Sequential)]
public struct POINT
{
public long X;
public long Y;
}
[StructLayout(LayoutKind.Sequential)]
public struct WNDCLASSEX
{
public uint cbSize;
public uint style;
public WndProc lpfnWndProc;
public int cbClsExtra;
public int cbWndExtra;
public IntPtr hInstance;
public IntPtr hIcon;
public IntPtr hCursor;
public IntPtr hbrBackground;
[MarshalAs(UnmanagedType.LPStr)]
public string lpszMenuName;
[MarshalAs(UnmanagedType.LPStr)]
public string lpszClassName;
public IntPtr hIconSm;
}
Program.cs:
class Program
{
static long WndProc(IntPtr hWnd, uint message, byte wParam, long lParam)
{
return WindowLL.DefWindowProcA(hWnd, message, wParam, lParam);
}
static void Main(string[] args)
{
var winCalss = new WNDCLASSEX() {
lpszClassName = "test",
lpfnWndProc = WndProc,
cbSize = (uint)Marshal.SizeOf(typeof(WNDCLASSEX)),
};
var classId = WindowLL.RegisterClassExA(ref winCalss);
var overlapped =
WindowStyle.Overlapped |
WindowStyle.Caption |
WindowStyle.SysMenu |
WindowStyle.ThickFrame |
WindowStyle.MinimizeBox |
WindowStyle.MaximizeBox;
IntPtr hWnd = WindowLL.CreateWindowExA(0,
classId, "test",
(uint)overlapped,
0, 0,
1280, 720,
IntPtr.Zero, IntPtr.Zero,
IntPtr.Zero, IntPtr.Zero
);
WindowLL.ShowWindow(hWnd, (int)NCmdShow.Show);
while (WindowLL.GetMessage(out var msg, hWnd, 0, 0)) {
WindowLL.TranslateMessage(ref msg);
WindowLL.DispatchMessage(ref msg);
}
}
}
Your structures are mostly wrong.
wParam / lParam should both be IntPtr, time should be uint, point x/y should be int.
You don't even need to write them yourself, copy-paste from the framework, MIT license allow that:
https://source.dot.net/#WindowsBase/System/Windows/Interop/MSG.cs,8a0b462145bdb8d8
https://source.dot.net/#PresentationFramework/System/Windows/Standard/NativeMethods.cs,527982c752231945
One more thing. You should not be using A-functions and structures like CreateWindowExA. These are compatibility shims for Windows 95, 98 and Me, all 3 discontinued decades ago. Modern software should only use W-versions. As a nice side effect strings marshalling is way cheaper, C# strings are stored as UTF-16 which matches the encoding expected by W WinApi functions.
The application will be installed by users from different countries, and what languages the keyboard layout of a specific user is unknown. We need a way with which the keyboard layout will change.
[DllImport("user32.dll")]
public static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern bool PostMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
public void ChangeLanguage()
{
PostMessage(GetForegroundWindow(), 0x0050, 2, 0);
}
I want to set the text of my Edit Control. When I do, the new content is Chinese.
For example, this:
[DllImport("user32.dll")]
public static extern int SendMessageW([InAttribute] System.IntPtr hWnd, int Msg, int wParam, string lParam);
[DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
internal static extern IntPtr GetFocus();
IntPtr c = GetFocus();
SendMessageW(c, 12, 0, "Test"); //Notice that 12 = WM_SETTEXT
sets my Edit Control to this: 敔瑳
According to pinvoke.net, you need a MarshalAs attribute on the string parameter:
[DllImport("user32.dll")]
public static extern int SendMessageW(
[InAttribute] System.IntPtr hWnd,
int Msg,
int wParam,
[MarshalAs(UnmanagedType.LPWStr)] string lParam);
I've been doing a program to send a text and enter key on a background running program , the sendmessage (string) works fine but after I call postmessage(VK_ENTER) it works only if the window is focused
here is code in C# (Visual Studio 2016)
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("User32.Dll", EntryPoint = "PostMessageA")]
private static extern bool PostMessage(IntPtr hWnd, uint msg, int wParam, IntPtr lParam);
[DllImport("User32.dll")]
public static extern int SendMessage(IntPtr hWnd, int uMsg, int wParam, string lParam);
[DllImport("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, int Msg, uint wParam, uint lParam);
private static string SetText(IntPtr handle)
{
const int VK_RETURN = 0x0D;
const int WM_KEYDOWN = 0x100;
SendMessage(handle, 0x000C, 0, textSend);
PostMessage(handle, WM_KEYDOWN, VK_RETURN, IntPtr.Zero);
}
Also I've tried with Sendmessage and it has the same result (the VK_RETURN isn't sent only if the window is not focused).
Any helper class anywhere which wrapps kernel32 APIs, with all functions-methods and structures? Or any wrapper generator?
I want ALL methods of kernel32.dll in C# like this:
[DllImport("kernel32.dll",EntryPoint="RtlMoveMemory")]
public static extern void RtlMoveMemory(int des, int src, int count);
[DllImport("kernel32.dll", EntryPoint = "OpenProcess")]
public static extern IntPtr OpenProcess(uint dwDesiredAccess, bool bInheritHandle, uint dwProcessId);
[DllImport("kernel32", CharSet = CharSet.Ansi)]
public extern static int GetProcAddress(int hwnd, string procedureName);
[DllImport("kernel32.dll", EntryPoint = "GetModuleHandle")]
public static extern int GetModuleHandle(string lpModuleName);
[DllImport("kernel32.dll", EntryPoint = "VirtualAllocEx")]
public static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect);
[DllImport("kernel32")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CloseHandle(IntPtr hObject);
[DllImport("kernel32", EntryPoint = "CreateRemoteThread")]
public static extern IntPtr CreateRemoteThread(IntPtr hProcess, IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, uint lpThreadId);
[DllImport("kernel32.dll", EntryPoint = "WriteProcessMemory")]
public static extern IntPtr WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] buffer, uint size, IntPtr lpNumberOfBytesWritten);
I doubt it.
Have you seen http://www.pinvoke.net/?