|
|
50.1 How to add an extern reference to a Win32 API?
|
 |
We have two suggestions with sample projects how you host a WebBrowser control inside a form and display HTML contents and listen to events such as NavigateComplete or BeforeNavigate. Of course there are many other ways to do this.
Download htmlviewer.zip for two sample projects for the suggestions discussed below.
1) The first suggestion is to generate an ActiveX wrapper for shdocvw using the aximp tool.
The command line for this tool should be as follows:
|
aximp c:\windows\system32\shdocvw.dll
|
This will generate the following assemblies.
|
Generated Assembly: D:\Syncfusion\faq\HtmlBrowser\HtmlViewer2\SHDocVw.dll
|
Generated Assembly: D:\Syncfusion\faq\HtmlBrowser\HtmlViewer2\AxSHDocVw.dll
|
Now you can reference these dlls in your project and use AxWebBrowser. In the attached HtmlViewer2 sample we have derived a HtmlControl class from AxWebBrowser and added some properties that let you specify a CSS Stylesheet and the Html content as a string.
2) Our second sample lets you bypass the generation of a ActiveX wrapper. You don't have to include and ship shdocvw.dll and axshdocvw.dll. In the attached HtmlViewer sample, we derived from AxHost and attached our own IWebBrowserEvents interface by overriding the CreateSink, AttachInterfaces and DetachSink methods.
You can use HtmlControl in your form and specify HTML content by assigning a HTML string to HtmlControl. A cascading style sheet can be specified by assigning a path name to the CascadingStyleSheet property. The sample demonstrates how to use a CSS style sheet that has been embedded as a resource in the assembly.
|
50.2 How do I hit a web page from within a button handler in my Windows Forms application?
|
 |
Use the Process class found in the System.Diagnostics namespace.
|
Process proc = new Process();
|
proc.StartInfo.UseShellExecute = true;
|
proc.StartInfo.FileName = @"http://www.microsoft.com";
|
// or just put it all as one statement
|
//System.Diagnostics.Process.Start(@"http://www.microsoft.com");
|
50.3 How can I capture output from an arbitrary console application from within my Window Form application?
|
 |
Use the Process class found in the System.Diagnostic namespace.
|
Process proc = new Process();
|
// test.exe is a console application generated by VC6
|
proc.StartInfo.FileName = @"C:\test\test.exe";
|
proc.StartInfo.Arguments = "";
|
proc.StartInfo.CreateNoWindow = true;
|
proc.StartInfo.UseShellExecute = false;
|
proc.StartInfo.RedirectStandardOutput = true;
|
string output = proc.StandardOutput.ReadToEnd();
|
//output now holds what text.exe would have displayed to the console
|
50.4 How do I convert LParam in a message from IntPtr to the Win32 type?
|
 |
Define the struct you want, for example RECT |
public int left, top, right, bottom;
|
Then use the Message.GetLPAram method |
RECT rc = (RECT)m.GetLParam( typeof(RECT) );
|
50.5 How do I maximize my main window?
|
 |
To maximize the main window, you can get the handle of the main window in the new process, and then send a SC_MAXIMIZE system command message to it. You can get the handle through the Process.MainWindowHandle property. To send a message you should use the DllImportAttribute attribute to import the API function. This is a sample code:
|
public const int WM_SYSCOMMAND = 0x0112;
|
public const int SC_MAXIMIZE = 0xF030;
|
[DllImportAttribute ("user32.dll")]
|
public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
|
Process p = new Process();
|
p.StartInfo.FileName = @"D:\Program Files\test.exe";
|
WinAPI.SendMessage(p.MainWindowHandle, WinAPI.WM_SYSCOMMAND, WinAPI.SC_MAXIMIZE,0);
|
(from lion_noreply@microsoft.com on microsoft.public.dotnet.framework.windowsforms)
|
50.6 How can I use 'Hooks' in .NET?
|
 |
Please check out this article from the October 2000 issue of MSDN Magazine.
Allen Weng gives the following explanation in a post on the microsoft.public.dotnet.framework.windowsforms newgroup.
If what you are looking for is just to intercept and handle generic Windows messages such as WM_NCPAINT or alike, you can override WndProc (). You don't need to use the hook procedure. Here is some code that does this:
|
protected override void WndProc(ref System.Windows.Forms.Message m)
|
if (m.Msg == (int) WinMsg.WM_PAINT)
|
m.Result = new IntPtr(0); // no further processing is needed.
|
But if you need to use a hook procedure, be cautious since they might interfere with normal execution of other applications. In some extreme cases, they might bring the whole system down if not processed correctly. Here is the code snippet that shows you how to do implement and use the hook procedure in .NET:
|
public static extern int GetCurrentThreadId();
|
[DllImport( "user32", CharSet=CharSet.Auto,CallingConvention=CallingConvention.StdCall)]
|
public static extern int SetWindowsHookEx( HookType idHook,
|
public delegate int HOOKPROC(int nCode, int wParam, int lParam);
|
private HOOKPROC hookProc; //private field with class scope
|
hookProc = new HOOKPROC(this.MyKeyboardProc);
|
SetWindowsHookEx(HookType.WH_KEYBOARD, hookProc, 0,
|
public int MyKeyboardProc(int nCode, int wParam, int lParam)
|
To install the hook procedure
|
Win32Hook hook = new Win32Hook();
|
50.7 Is there any way to get to the Edit control or the editHandle of a ComboBox using safe code?
|
 |
Bill Zhang (Microsoft) responds to this question in a posting on microsoft.public.dotnet.frameworks.windowsforms newsgroup.
|
The Frameworks classes use P/Invoke to call the GetWindow API to get the HWND internally - there is no exposed way to do this. If you wish to get the Win32 HWND, here's the code to do it, but there is no way to get a
|
System.Windows.Forms.Edit control from this.
|
[DllImport("user32.dll", ExactSpelling=true, CharSet=CharSet.Auto)]
|
public static extern IntPtr GetWindow(IntPtr hWnd, int uCmd);
|
public const int GW_CHILD = 5;
|
if (combo.DropDownStyle != ComboBoxStyle.DropDownList) {
|
IntPtr hwnd = GetWindow(combo.Handle, NativeMethods.GW_CHILD);
|
if (hwnd != IntPtr.Zero) {
|
50.8 How do I get the associated Icon from a file in the file system?
|
 |
Here is a sample prepared by Matthias Heubi that uses interop to access SHGetFileInfo to retrieve icons.
You could also use the ExtractIconEx native api via PInvoke to extract the app icon. |
50.9 How can I get the directory name for "My Documents" folder and other system directories?
|
 |
public void CreateMyBorderlessWindow()
|
this.FormBorderStyle = FormBorderStyle.None;
|
this.MaximizeBox = false;
|
this.MinimizeBox = false;
|
this.StartPosition = FormStartPosition.CenterScreen;
|
50.10 How can I show a form without making it active?
|
 |
Normally when you make a Form visible by setting the Visible property to true, it will show the form and set the focus too. In some cases however, you do not want it to take focus until the user clicks on it. To get this behavior, do the following utility code:
When you want to show a form without activating it: |
UtilFuncs.SetVisibleNoActivate(myForm, true); // true to show.
|
When you want to hide it: |
UtilFuncs.SetVisibleNoActivate(myForm, false); // false to hide.
|
[DllImport("USER32.dll")]
|
extern public static bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, int uFlags) ;
|
public const int HWND_TOPMOST = -1; // 0xffff
|
public const int SWP_NOSIZE = 1; // 0x0001
|
public const int SWP_NOMOVE = 2; // 0x0002
|
public const int SWP_NOZORDER = 4; // 0x0004
|
public const int SWP_NOACTIVATE = 16; // 0x0010
|
public const int SWP_SHOWWINDOW = 64; // 0x0040
|
public const int SWP_HIDEWINDOW = 128; // 0x0080
|
public const int SWP_DRAWFRAME = 32; // 0x0020
|
public static void ShowWindowTopMost(IntPtr handle)
|
(IntPtr)HWND_TOPMOST, 0, 0, 0, 0,
|
SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_SHOWWINDOW);
|
public static void SetVisibleNoActivate(Control control, bool visible)
|
ShowWindowTopMost(control.Handle);
|
50.11 How to access a winapi that has a LPTSTR and maxlen param?
|
 |
[DllImport("user32.dll", CharSet=CharSet.Auto, CallingConvention=CallingConvention.Winapi)]
|
public static extern int GetMenuString(IntPtr hMenu, uint uIDItem, [MarshalAs(UnmanagedType.LPTStr)]string lpString,int maxCount,uint uFlag);
|
String caption = new String('t', 30);//using a dummy char ‘t' here.
|
int len = GetMenuString(hsysmenu, commandID, caption, 30, 0));
|
50.12 How do I use an exported function (extern "C") from a legacy DLL?
|
 |
Use the DllImport attribute that is a member of the System.Runtime.InteropServices namespace. Assume your exported function found in MyDLL.dll has a signature: |
int MyFunction( LPCTSTR lpCaption, UINT uType);
|
The code below shows how you can access this function from within C#.
|
using System.Runtime.InteropServices;
|
public int MyFunction(string title, int type);
|
public static void Main()
|
int nReturnValue = MyFunction("some string", 14);
|
50.13 How can I draw outside my WIndow?
|
 |
You have to get a handle to the desktop and draw on the desktop. This means that whatever you draw will not be automatically refreshed when another window is dragged over it.
|
[DllImport("User32.dll")]
|
public extern static System.IntPtr GetDC(System.IntPtr hWnd);
|
private void button1_Click(object sender, System.EventArgs e)
|
System.IntPtr DesktopHandle = GetDC(System.IntPtr.Zero);
|
Graphics g = System.Drawing.Graphics.FromHdc(DesktopHandle);
|
g.FillRectangle(new SolidBrush(Color.Red),0,0,100,100);
|
from a microsoft.public.dotnet.framework.windowsforms posting by Lion Shi (MS) |
50.14 Is there any way to get detailed error information for Win32 errors when using Platform Invoke?
|
 |
Yes, you can use the FormatMessage Win32 API. Sample projects for C# and VB.NET are enclosed. This is how the declaration looks like:
|
[DllImport("Kernel32.dll")]
|
public static extern int FormatMessage(int flags, IntPtr source, int messageId, int languageId, StringBuilder
|
buffer, int size, IntPtr arguments );
|
// You can call FormatMessage to get a descriptive error message
|
StringBuilder sbFormatMessage = new StringBuilder(1024);
|
retVal = Interop.FormatMessage(Interop.FORMAT_MESSAGE_FROM_SYSTEM, IntPtr.Zero, Marshal.GetLastWin32Error(), 0, sbFormatMessage,
|
sbFormatMessage.Capacity, IntPtr.Zero);
|
|
|
|
|