|
|
|
The General Winforms Interview Questions consists the most frequently
asked questions in Winforms. This list of 100+ questions guage your familiarity
with the Winforms platform. The q&a have been collected over a period
of time from various blogs, forums and other similar Winforms sites
|
41. Interoperability Win32
|
| 41.1 How to add an
extern reference to a Win32 API?
|
| 41.2 How do I hit a
web page from within a button handler in my Windows Forms application?
|
| 41.3 How can I
capture output from an arbitrary console application from within my Window Form
application?
|
| 41.4 How do I convert
LParam in a message from IntPtr to the Win32 type?
|
| 41.5 How do I
maximize my main window?
|
| 41.6 How can I use
'Hooks' in .NET?
|
| 41.7 Is there any way
to get to the Edit control or the editHandle of a ComboBox using safe code?
|
| 41.8 How do I get the
associated Icon from a file in the file system?
|
| 41.9 How can I get
the directory name for "My Documents" folder and other system directories?
|
| 41.10 How can I show
a form without making it active?
|
| 41.11 How to access
a winapi that has a LPTSTR and maxlen param?
|
| 41.12 How do I use
an exported function (extern "C") from a legacy DLL?
|
| 41.13 How can I draw
outside my WIndow?
|
| 41.14 Is there any
way to get detailed error information for Win32 errors when using Platform
Invoke?
|
41.1 How to add an extern reference to a Win32 API?
|
|
e 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.
|
41.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";
proc.Start();
// or just put it all as one statement
//System.Diagnostics.Process.Start(@"http://www.microsoft.com");
|
41.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;
proc.Start();
string output = proc.StandardOutput.ReadToEnd();
//output now holds what text.exe would have displayed to the console
|
41.4 How do I convert LParam in a message from IntPtr to the Win32 type?
|
|
Define the struct you want, for example RECT
|
struct RECT
{
public int left, top, right, bottom;
}
|
|
Then use the Message.GetLPAram method
|
|
RECT rc = (RECT)m.GetLParam( typeof(RECT) );
|
41.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 class WinAPI
{
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";
p.Start();
WinAPI.SendMessage(p.MainWindowHandle, WinAPI.WM_SYSCOMMAND,
WinAPI.SC_MAXIMIZE,0);
|
45.6 How can I use 'Hooks' in .NET?
|
|
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:
|
public enum WinMsg
{
WM_KEYDOWN = 256,
WM_KEYUP = 257,
WM_PAINT = 15,
WM_CREATE = 1
.......
.......
};
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.
.......
.......
}
..............
base.WndProc(ref m);
}
|
|
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 class Win32Hook
{
[DllImport("kernel32")]
public static extern int GetCurrentThreadId();
[DllImport(
"user32",CharSet=CharSet.Auto,CallingConvention=CallingConvention.StdCall)]
public static extern int SetWindowsHookEx( HookType idHook,
HOOKPROC lpfn,
int hmod,
int dwThreadId
);
public enum HookType
{
WH_KEYBOARD = 2
}
public delegate int HOOKPROC(int nCode, int wParam, int lParam);
private HOOKPROC hookProc; //private field with class scope
public void SetHook()
{
// set the keyboard hook
hookProc = new HOOKPROC(this.MyKeyboardProc);
SetWindowsHookEx(HookType.WH_KEYBOARD, hookProc, 0,
GetCurrentThreadId());
}
public int MyKeyboardProc(int nCode, int wParam, int lParam)
{
return 0;
}
}
|
|
To install the hook procedure
|
Win32Hook hook = new Win32Hook();
hook.SetHook();
|
41.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) {
editHandle = hwnd;
}
}
|
41.8 How do I get the associated Icon from a file in the file system?
|
|
You could also use the ExtractIconEx native api via PInvoke to extract the app
icon.
|
41.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;
this.ControlBox = false;
}
|
41.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.
|
|
|
public class UtilFuncs
{
[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)
{
SetWindowPos(handle,
(IntPtr)HWND_TOPMOST, 0, 0, 0, 0,
SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_SHOWWINDOW);
}
public static void SetVisibleNoActivate(Control control, bool visible)
{
if(visible)
{
ShowWindowTopMost(control.Handle);
control.Visible = true;
}
else
control.Visible = false;
}
}
|
37.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);
//Usage:
String caption = new String('t', 30);//using a dummy char ‘t' here.
int len = GetMenuString(hsysmenu, commandID, caption, 30, 0));
|
41.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;
using System.Runtime.InteropServices;
class HelloWorld
{
[DllImport("mydll.dll")]
public int MyFunction(string title, int type);
public static void Main()
{
int nReturnValue = MyFunction("some string", 14);
}
}
|
41.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);
}
|
41.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 );
|
|
Called like so:
|
/ 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);
|
|