How to call DrawThemeTextEx in .NET - c#

I need to write a text with glow in a Vista/seven glass window, and I'm, trying to call the API to write some text there. I have checked out a great sample in CodeProject, but the problem is that I'm using .NET 1 (please, don't ask :-)
I need to translate the follwing .NET 2 code to PInvoke, .NET 1 code.
// using System.Windows.Forms.VisualStyles
VisualStyleRenderer renderer = new VisualStyleRenderer(
VisualStyleElement.Window.Caption.Active);
// call to UxTheme.dll
DrawThemeTextEx(renderer.Handle,
memoryHdc, 0, 0, text, -1, (int)flags,
ref textBounds, ref dttOpts);
The class VisualStyleRenderer does not exist in .NET 1, so I need to get the renderer.Handle in other way.

Define the OpenThemeData API and DrawThemeTextEx, as well as some required structs and constants:
[DllImport("uxtheme.dll", CharSet = CharSet.Unicode)]
private static extern IntPtr OpenThemeData(IntPtr hwnd, string pszClassList);
[DllImport("uxtheme.dll", CharSet = CharSet.Unicode)]
private extern static Int32 DrawThemeTextEx(IntPtr hTheme, IntPtr hdc, int iPartId, int iStateId, string pszText, int iCharCount, uint flags, ref RECT rect, ref DTTOPTS poptions);
[StructLayout(LayoutKind.Sequential)]
private struct RECT
{
public int left;
public int top;
public int right;
public int bottom;
}
[StructLayout(LayoutKind.Sequential)]
private struct DTTOPTS
{
public int dwSize;
public int dwFlags;
public int crText;
public int crBorder;
public int crShadow;
public int iTextShadowType;
public int ptShadowOffsetX;
public int ptShadowOffsetY;
public int iBorderSize;
public int iFontPropId;
public int iColorPropId;
public int iStateId;
public bool fApplyOverlay;
public int iGlowSize;
public IntPtr pfnDrawTextCallback;
public IntPtr lParam;
}
// taken from vsstyle.h
private const int WP_CAPTION = 1;
private const int CS_ACTIVE = 1;
And then, call it like this:
IntPtr handle = OpenThemeData(IntPtr.Zero, "WINDOW");
DrawThemeTextExt(handle, hdc, WS_CAPTION, CS_ACTIVE, ...)
The WS_CAPTION and CS_ACTIVE values match .NET 2's Caption and Active respectively. Values are described here officially: Parts and States

In short, you get what you want by calling OpenThemeData().
To work out all the details it would be much easier for you to write a sample app in C++ to get to know how to drive the theme API from the ground up. There are many tutorials and lots of sample code on the web. But do it in C++ where you will have all the functions readily available. The last thing you want to get doing is fighting with P/Invokes whilst you are also getting to grips with low-level theme API.
Once you get it cracked in C++, then move on to the P/Invokes and if you have trouble it will be easy to refer back to the C++ code that works.

Related

How can I use SHFileOperation in C#?

I'm trying to move a folder from directory to another directory , but I'm getting an exception of access to path is denied , so I found a c++ SHFileOperation method that can be used in this case, the problem is that I didn't have any idea how to use it:
public void MoveFolder(string oldPath,string newPath)
{
SHFILEOPSTRUCT hFILEOPSTRUCT = new SHFILEOPSTRUCT();
hFILEOPSTRUCT.pFrom = oldPath;
hFILEOPSTRUCT.pTo = newPath;
int res = SHFileOperation(ref hFILEOPSTRUCT);
}
[DllImport("shell32.dll", CharSet = CharSet.Auto, SetLastError = true,
ThrowOnUnmappableChar = true)]
[Obsolete]
static extern int SHFileOperation(ref SHFILEOPSTRUCT lpFileOp);
Struct definition of SHFILEOPSTRUCT:
[Obsolete("Use this element with caution and only if you know what you are doing. It's only meant to be used internally by MahApps.Metro and Fluent.Ribbon. Breaking changes might occur anytime without prior warning.")]
public struct SHFILEOPSTRUCT
{
public IntPtr hwnd;
public FO wFunc;
public string pFrom;
public string pTo;
[CLSCompliant(false)]
public FOF fFlags;
public int fAnyOperationsAborted;
public IntPtr hNameMappings;
public string lpszProgressTitle;
}
}
This code throw an exception
Cannot marshal field 'fAnyOperationsAborted' of type 'ControlzEx.Standard.SHFILEOPSTRUCT': Invalid managed/unmanaged type combination (Int32/UInt32 must be paired with I4, U4, or Error).
How can I make this works?

In C#, given an intptr to a window handle, how do I measure this window handle's true height using scrollinfo

I have a sub-window within a scroll window in a separate application. I am attempting to use a C# console application to inspect that scroll-window's true height (not its on screen height, but the height in pixels of how many pixels can be scrolled). I know using the existing user32.dll libs I can ask for a scroll info but that gives me details about the scrollbar itself, the scrollbar's height and position, but it doesn't give me the total pixels that the scrollbar would scroll through.
[DllImport("User32.dll")]
private static extern bool GetScrollInfo(IntPtr hwnd, int fnBar, ref ScrollInfo lpsi);
Is there a way I can use the scrollinfo returned by the above method to derive the actual pixels of the scrollable area?
public struct ScrollInfo
{
public uint cbSize;
public uint fMask;
public int nMin;
public int nMax;
public uint nPage;
public int nPos;
public int nTrackPos;
}

c# using properties in struct scope, when used for winapi?

I kindly wanted to ask if it is recommendable to add properties for fields in a struct scope, if the struct is used for an winAPI call (f.ex. dllimport("xxx.dll")).
The question poped up when I let run the code Analysis - saying me, that I should use property accessors instead having public fields in struct.
And true, onthinking I would recommend that too, but - is an API call still possible with the 'so code optimized' struct?
May be I ought to show what I mean:
as everybody knows it:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
struct someAPICallStructure
{
public int cbSize;
public IntPtr hwndParent;
public string pszMessageText;
public string pszCaptionText;
public IntPtr hbmBanner;
}
as the code analyzer wishes:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
struct someAPICallStructure
{
public CBSize
{
get
{
return cbSize;
}
set
{
cbSize = value;
}
}
.... and properties for all other fields too ...
int cbSize;
IntPtr hwndParent;
string pszMessageText;
string pszCaptionText;
IntPtr hbmBanner;
}
Or could I even use like this?
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
struct someAPICallStructure
{
public CBSize {get; set;}
... and with all other fields too ...
}
And even further; can I add equals(..) and other suggested methods to the struct and it works still for the API Call?

How to differenciate mousemove inputs of multiple mouse devices?

I have a mouse and a touchpad on my laptop. I want a global hook for mousemove that tells me not only the new position, but also the physical device where it came from. Subscribing the hook only to the touchpad would be an even better solution, since I'm only interested in the touchpad. The hook has to work system wide (even if my application is not in focus).
How can I do this?
I'm not afraid to use Pinvoke in my C#/WPF application
You could use
P-Invoke user32.getrawinputdeviceinfo .
For mouse input you can get thing such:
[StructLayout(LayoutKind.Sequential)]
internal struct RID_DEVICE_INFO_MOUSE
{
[MarshalAs(UnmanagedType.U4)]
public int dwId;
[MarshalAs(UnmanagedType.U4)]
public int dwNumberOfButtons;
[MarshalAs(UnmanagedType.U4)]
public int dwSampleRate;
[MarshalAs(UnmanagedType.U4)]
public int fHasHorizontalWheel;
}
and, about Device:
StructLayout(LayoutKind.Sequential)]
internal struct RID_DEVICE_INFO_HID
{
[MarshalAs(UnmanagedType.U4)]
public int dwVendorId;
[MarshalAs(UnmanagedType.U4)]
public int dwProductId;
[MarshalAs(UnmanagedType.U4)]
public int dwVersionNumber;
[MarshalAs(UnmanagedType.U2)]
public ushort usUsagePage;
[MarshalAs(UnmanagedType.U2)]
public ushort usUsage;
}

Marshalling nested struct from C# to C++ DLL

I am trying to call a function from C# to a .DLL written in Borland C++ whose signature is:
extern "C" __declspec(dllexport) ls50errortype __stdcall Ls50P2Open(ls50p2apiconfiginfostruct &configinfo);
The corresponding call in C#:
[DllImport("C:\\Lumistar\\LDPS_8x\\Ls50P2_Dll.dll", EntryPoint = "Ls50P2Open", CallingConvention = System.Runtime.InteropServices.CallingConvention.StdCall, CharSet = CharSet.Ansi, SetLastError = true)]
public static extern void Ls50P2Open(ref ls50p2apiconfiginfostruct configinfo);
The structure of interest (ls50p2apiconfiginfostruct) is composed of nested structures and enums (copied from the C++ header):
typedef enum
{
MFMODEL_LS50P1,
MFMODEL_4422PCI,
MFMODEL_LS50P2,
MFMODEL_LS70P2,
MFMODEL_LS5070,
MFMODEL_LAST
}ecardmodel;
typedef enum
{
CHANNELDEVICE_NONE,
CHANNELDEVICE_50,
CHANNELDEVICE_70,
CHANNELDEVICE_LAST
}ls50p2channeldevicetype;
typedef enum
{
LS50V2DCARD_NONE,
LS50V2DCARD_40V1_10,
LS50V2DCARD_40V1_20,
LS50V2DCARD_40V2_10,
LS50V2DCARD_40V2_20,
LS50V2DCARD_38,
LS50V2DCARD_LAST
}ls50p2daughtercardtype;
typedef struct
{
bool HasDaughterCard;
ls50p2daughtercardtype DCardType;
bool SpecialStatusCapable;
int MaxBitsyncInputs;
bool HasBitsyncConfidenceLevel;
bool HasBitsync2ndCh;
bool SpecialStatusCapable2ndCh;
bool HasBitsyncConfidenceLevel2ndCh;
ls50p2daughtercardtype DCardType2ndCh;
int MaxBitsyncInputs2ndCh;
}ls50p2daughtercardinfostruct;
typedef struct
{
ecardmodel DeviceModel;
ls50p2channeldevicetype ChannelDataTypeAry[2];
ls50p2daughtercardinfostruct DaughterCardInfo;
bool HasExtendedBertPatterns;
int FirmwareVersionAry[2];
int NumPremodFiltersAry[2];
double Ls50SimPreModFilterKhzAry[2][LS50V2_MAX50SIMPREMODFILTERS];
double Ls50SimMinFmDeviationKhzAry[2];
double Ls50SimMaxFmDeviationKhzAry[2];
}ls50p2cardconfigstruct;
typedef struct
{
unsigned char *DataBuf;
HANDLE hNewDataRdy;
DWORD MaxBufLength;
DWORD CurrentBufLength;
int NumHeaderBytes;
}ls50p2carddatastruct;
typedef struct
{
ls50p2cardconfigstruct CardConfigInfo[MAXMFCARDS];
int Ls50P2CardCount;
ls50p2carddatastruct DataInfo[MAXMFCARDS][2];
}ls50p2apiconfiginfostruct;
Here's the corresponding struct in C#:
public enum ecardmodel
{
MFMODEL_LS50P1,
MFMODEL_4422PCI,
MFMODEL_LS50P2,
MFMODEL_LS70P2,
MFMODEL_LS5070,
MFMODEL_LAST
}
public enum ls50p2channeldevicetype
{
CHANNELDEVICE_NONE,
CHANNELDEVICE_50,
CHANNELDEVICE_70,
CHANNELDEVICE_LAST
};
public enum ls50p2daughtercardtype
{
LS50V2DCARD_NONE,
LS50V2DCARD_40V1_10,
LS50V2DCARD_40V1_20,
LS50V2DCARD_40V2_10,
LS50V2DCARD_40V2_20,
LS50V2DCARD_38,
LS50V2DCARD_LAST
}
[StructLayout(LayoutKind.Sequential)]
public struct ls50p2daughtercardinfostruct
{
public bool HasDaughterCard;
public ls50p2daughtercardtype DCardType;
public bool SpecialStatusCapable;
public int MaxBitsyncInputs;
public bool HasBitsyncConfidenceLevel;
public bool HasBitsync2ndCh;
public bool SpecialStatusCapable2ndCh;
public bool HasBitsyncConfidenceLevel2ndCh;
public ls50p2daughtercardtype DCardType2ndCh;
public int MaxBitsyncInputs2ndCh;
}
[StructLayout(LayoutKind.Sequential)]
public struct ls50p2cardconfigstruct
{
public ecardmodel DeviceModel;
public ls50p2daughtercardtype[] ChannelDataTypeAry;
public ls50p2daughtercardinfostruct DaughterCardInfo;
public bool HasExtendedBertPatterns;
public int[] FirmwareVersionAry;
public int[] NumPremodFiltersAry;
public double[] Ls50SimPreModFilterKhzAry;
public double[] Ls50SimMinFmDeviationKhzAry;
public double[] Ls50SimMaxFmDeviationKhzAry;
}
[StructLayout(LayoutKind.Sequential)]
public struct ls50p2carddatastruct
{
public StringBuilder DataBuf;
public IntPtr hNewDataRdy;
public uint MaxBufLength;
public uint CurrentBufLength;
public int NumHeaderBytes;
}
[StructLayout(LayoutKind.Sequential)]
public struct ls50p2apiconfiginfostruct
{
public ls50p2cardconfigstruct[] CardConfigInfo;
public int Ls50P2CardCount;
public ls50p2carddatastruct[,] DataInfo;
}
Here's the code in C# that I use to call the function:
ls50p2apiconfiginfostruct lscfg = new ls50p2apiconfiginfostruct();
lscfg.CardConfigInfo = new ls50p2cardconfigstruct[8];
for (int i = 0; i < 8; i++)
{
lscfg.CardConfigInfo[i].ChannelDataTypeAry = new ls50p2daughtercardtype[2];
}
lscfg.DataInfo = new ls50p2carddatastruct[8, 2];
Ls50P2Open(ref lscfg);
I have tried making this struct in C# but I haven't had much success (problems with enums, 2D arrays, fixed sized buffers). What is the correct way to create this structure in C#? Would this need to be done in an unsafe context?
Now for some reason I get the following error when running the code:
An unhandled exception of type 'System.Runtime.InteropServices.COMException' occurred in Library.dll
Additional information: Old format or invalid type library. (Exception from HRESULT: 0x80028019 (TYPE_E_UNSUPFORMAT))
What does your C# structure looks like. Are you using the StructLayoutAttribute?
http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.structlayoutattribute.aspx
You can use it with the option sequential so you just would have to fill your c# structure with fields in the right order.
I believe the array problem is more or less answered here; Improper marshaling: C# array to a C++ unmanaged array
The accepted answer shows how to safely marshal a dynamically allocated array.
As for the enums, they shouldn't pose any problems, there is a clean 1:1 mapping. In fact, I would do it as described in this msdn post; http://blogs.msdn.com/b/abhinaba/archive/2007/08/27/sharing-enums-across-c-and-c.aspx
You can simply define all your enums in a .cs file then include it in both projects and everything will work fine.

Categories

Resources