|
Wow! One of the best answers I've received here at CodeProject.
Thanks a bunch for the links.
I'll work through it and see what I can do.
Thanks again.
|
|
|
|
|
Hmm. I'm sure this is a totally rookie problem.
I've done my fair share of casting in C++, but I'm pretty new to C#.
How do I cast the lParam to my NMHDR struct in C#?
In my class (which per the link you supplied is derived from NativeWindow), I have NMHDR defined:
private struct NMHDR
{
IntPtr hwndFrom;
IntPtr idFrom;
UInt32 code;
}
Then in the overridden WndProc, I have:
if (m.Msg == WM_NOTIFY)
{
}
And since I am pretty new to C#, I don't know the syntax for this casting.
|
|
|
|
|
OK. I answered my own question.
In case anyone else out there runs into this sort of problem, here's what I found (and it seems to be working):
if (m.Msg == WM_NOTIFY)
{
NMHDR nmHdr = new NMHDR();
nmHdr = (NMHDR)m.GetLParam(typeof(NMHDR));
if (nmHdr.code == NM_CUSTOMDRAW)
{
Debug.WriteLine("Got here.");
}
}
But now I have a different question (there's always something):
Where can I find all the info on the struct.s I need (including, but not necessarily limited to: NMHDR, NMCUSTOMDRAW and NMLVCUSTOMDRAW)? I can find them easily enough by searching MS KB, but is there a file somewhere that I can cut and paste from or just include in my code that already has all of this stuff defined (in C#)? Manually coding all of the structs is kind of a pain.
Thanks.
|
|
|
|
|
You may find what you need at PInvoke.net[^], but they don't have all of the Win32 structures defined.
|
|
|
|
|
Boy, I hope you're not getting irritated with this thread yet because I like learning stuff.
I'm just wondering if you've ever actually attempted what I'm talking about here. Your original response, and the associated links, made it seem as though this might be fairly easy. Unfortunately, the more I learn about it, the harder it seems to be getting.
I was thinking about writing an article discussing OwnerDraw vs CustomDraw to customize the look of a ListView, but the CustomDraw thing seems to be monumental. Just from the standpoint of defining all the structs involved: NMHDR is easy, NMCUSTOMDRAW is fairly straightforward but even that also involves a RECT structure; don't even get me started on NMLVCUSTOMDRAW which involves RECT and COLORREF which itself is fairly complex.
I am persistently running into unhandled exceptions involving read/write to protected memory which I am figuring must be due to not having completely figured all the structs out yet.
I retrieve the LParam using:
nmlvCust = (NMLVCUSTOMDRAW)m.GetLParam(typeof(NMLVCUSTOMDRAW));
and put it back into the LParam using:
Marshal.StructureToPtr(nmlvCust, m.LParam, true);
But somewhere along the chain of messages, at the GetLParam point, I get the access violation.
If you have any suggestions or ideas, please offer. If not, then I figure I'll abandon this for now and perhaps come back to it some other time.
Regardless, thanks for your input -- it has certainly pointed me into areas I've not explored. It's been pretty cool thus far. Thanks.
|
|
|
|
|
David Fleming wrote: Boy, I hope you're not getting irritated with this thread yet because I like learning stuff.
Nope!
David Fleming wrote: I'm just wondering if you've ever actually attempted what I'm talking about here. Your original response, and the associated links, made it seem as though this might be fairly easy. Unfortunately, the more I learn about it, the harder it seems to be getting.
The devil is in the details! No, I've never attempted to do a custom-draw listview, but I've worked with notification messages before, and this is a pretty typical case for them. I've got a lot of experience with interop, which is why I make it sound easy... but it's only easy if you've dealt with this stuff a lot.
COLORREF ==int . You can use ColorTranslator.FromWin32() to convert it to a Color . Your NMLVCUSTOMDRAW structure should look like this:
[StructLayout(LayoutKind.Sequential)]
struct NMLVCUSTOMDRAW
{
NMCUSTOMDRAW customDraw;
int textColor;
int textBackColor;
int subItemIndex;
uint itemType;
int faceColor;
int iconEffect;
int iconPhase;
int partID;
int stateID;
RECT textRect;
uint groupAlignment;
}
NMCUSTOMDRAW , RECT , and NMHDR can be found on PInvoke.net[^].
Let me know if this is the same as or different than what you are doing. If it is the same, then the problem must lie elsewhere besides the struct definitions.
If you need to support versions before Common Controls 6, but still want to support the XP features when they're available, you can use a BinaryReader instead of structures. I'll give you more on that if you want.
|
|
|
|
|
The struct I had defined was pretty much the same except for the COLORREF parts. I had seen on PInvoke what you said about COLORREF being an int.
The good news is that the memory exception went away when I fixed all the structs (using mine as well as your new one).
The bad news is that it still isn't actually doing anything.
I'll include my overridden WndProc for you to look at, and I'll make a couple of comments on it below:
protected override void WndProc(ref System.Windows.Forms.Message m)
{
base.WndProc(ref m);
if (m.Msg == WM_NOTIFY)
{
nmlvCust = (NMLVCUSTOMDRAW)m.GetLParam(typeof(NMLVCUSTOMDRAW));
if (nmlvCust.nmcd.hdr.code == NM_CUSTOMDRAW)
{
m.Result = (IntPtr)CDRF_DODEFAULT;
Debug.WriteLine("In CustomDraw. dwDrawStage = " + nmlvCust.nmcd.dwDrawStage ". Result = " + m.Result);
if (nmlvCust.nmcd.dwDrawStage == CDDS_PREPAINT)
{
m.Result = (IntPtr)CDRF_NOTIFYITEMDRAW;
Debug.WriteLine("In PrePaint. dwDrawStage = " + nmlvCust.nmcd.dwDrawStage + ". Result = " + m.Result);
}
else if (nmlvCust.nmcd.dwDrawStage == CDDS_ITEMPREPAINT)
{
m.Result = (IntPtr)CDRF_NOTIFYSUBITEMDRAW;
Debug.WriteLine("In ItemPrePaint. dwDrawStage = " + mlvCust.nmcd.dwDrawStage + ". Result = " + m.Result);
}
else if (nmlvCust.nmcd.dwDrawStage == (CDDS_ITEMPREPAINT | CDDS_SUBITEM))
{
if (nmlvCust.iSubItem == 0)
{
nmlvCust.clrText = ColorTranslator.ToWin32(SystemColors.Control);
nmlvCust.clrTextBk = ColorTranslator.ToWin32(SystemColors.Info);
}
else if (nmlvCust.iSubItem == 1)
{
nmlvCust.clrText = ColorTranslator.ToWin32(SystemColors.WindowText);
nmlvCust.clrTextBk = ColorTranslator.ToWin32(SystemColors.Window);
}
else
{
nmlvCust.clrText = ColorTranslator.ToWin32(SystemColors.HighlightText);
nmlvCust.clrTextBk = ColorTranslator.ToWin32(SystemColors.Highlight);
}
m.Result = (IntPtr)CDRF_NOTIFYSUBITEMDRAW;
Debug.WriteLine("In SubItem. dwDrawStage = " + nmlvCust.nmcd.dwDrawStage + ". Result = " + m.Result);
}
}
Marshal.StructureToPtr(nmlvCust, m.LParam, true);
}
}
What I've noticed is that everything seems to be working OK except that we never get dwDrawStage equal to CDDS_ITEMPREPAINT | CDDS_SUBITEM. You will notice that the constants for CDRF_NOTIFYITEMDRAW and CDRF_NOTIFYSUBITEMDRAW are the same (0x20). In the cmmctrl.h file, they are in fact the same with a little note to the side of CDRF_NOTIFYSUBITEMDRAW saying:
So, there are two things I just don't get at this point:
1) Even though I essentially lifted this code directly from Michael Dunn's article (which, by the way I have used in C++ and it worked beautifully), the logic isn't working here like it does under C++ -- somehow, under C#, we're just not getting dwDrawStage == CDDS_ITEMPREPAINT | CDDS_SUBITEM like we do under C++.
2) Another thing I've noticed is that the iSubItem member of the NMLVCUSTOMDRAW is not getting set. I presume this has something to do with problem #1, since we evidently are not actually getting to the SubItem part of drawing.
Also, even if I eliminate the subitem part of the logic and try setting colors in the item level, it still does not actually cause any change on the screen. All I can notice upon running the program is that the first item in the ListView flashes very quickly. I assume something is being done, just not what I want.
Any suggestions on why the logic isn't getting down to the subitem level? or what to do next?
Thanks. BTW, let me know if you run out of patience or time for this -- I do this stuff just for fun -- I'm guessing you do this sort of thing for a living.
-- modified at 17:50 Thursday 1st March, 2007
Something else I noticed is that the dwItemSpec of the NMCUSTOMDRAW struct (which is a member of the NMLVCUSTOMDRAW struct) seems to correspond to the subitem (or column), because when I change the number of columns and watch the loop cycle through, the dwItemSpec always has the same number of iterations as the number of columns. So what I'm thinking might be happening here is that I am getting the subitems but not getting each ITEM. First, I don't know how to confirm that or rule it out, and second, I don't know what to do about it if that is the case.
|
|
|
|
|
I created a new control derived from MaskedTextBox. The new control should react on a change of its Culture property, i.e. if the user changes the Culture something like a CultureChanged(object sender, someArgs e) event should be fired. I want to use this event to change some internal setting in the new control.
I have no clue how I can attach an event to the Culture property so it is fired, when the value of Culture changes. I tried to override the Culture property and to fire an eventhandler there, but unfortunately Culture can not be overriden (or at least I didn't figure out how).
Has anybody an idea how I could do it? I would be very glad for any hint in which direction to go.
Thanks
Dirk
|
|
|
|
|
Take a look at the new Modifier[^].
"Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the Universe trying to produce bigger and better idiots. So far, the Universe is winning." - Rick Cook www.troschuetz.de
|
|
|
|
|
Dear All,
I have an n-tier application that is devided into main three parts:
1. UI -> Windows From (dot Net Framework 2.0).
2. BL -> Web Services.
3. DB -> SQL Server 2005.
The Problem Is:
There are crystal reports files on the server and i need to display them
but the windows form crystal viewer - as i know - doesn't take a URL as a report path and for security issues i cann't put my crystal files along with the exe or along with the client machine...
soo please help.....
Ala'a Al Atrash
Special Systems Co.
Culture St. - Amman - Jordan
Software Developer
Work Tel:- +962 6 5664221 Ext. 140
Home Tel:- +962 6 4752702
Mobile Tel:- +962 7 96700423
|
|
|
|
|
Hello All!
I am working on this FileSystemWatcher class. I am successful in updating an SQL database with the changes/events that fires from the FileSystemWatcher. But, when I convert this into an windows service using the aid of this link:
http://msdn2.microsoft.com/en-us/library/zt39148a(VS.80).aspx[^]
I am not able to update the database. The functionality/sln works fine when it is running on Visual Studio.
Can anyone post a link where sql db is used in the windows service?
Thanks in adv!
Ananth
|
|
|
|
|
Sounds like the user that runs your service does not have permissions to access your database.
Goto "Settings->Control Panel->Administrative Tools->Services". Open the properties for your service, then look at the "Log On" tab-page. This will tell you the user that is running your service. Then make sure that that user has permissions to log into your database and to access the file-system folders that you are watching.
|
|
|
|
|
There are no restrictions on a service updating an SQL database. The problem is probably caused by you using a Trusted Connection in your connection string instead of supplying an actual username and password to login to the SQL Server. Any normal service, by default, uses the LocalSystem account, which isn't going to be trusted by a remote SQL Server.
Dave Kreskowiak
Microsoft MVP - Visual Basic
|
|
|
|
|
I have a custom control in a form and I want it to catch the key I press, so I implement the "KeyDown" event, its ok but the event does not fire when I press TAB, Up, Down... (the keys that is used internal to change the tab index of control inside the form).
How can I disable it and handle those special keys?
Thank you for your help!
|
|
|
|
|
Hello,
When you use te KeyDown event the member 'KeyData' is what you are looking for.
if(e.KeyData == Keys.Tab)
{
e.Handled = true;
}
All the best,
Martin
|
|
|
|
|
But it is not go to the KeyDown method at all when you press Tab, we can not check it.
|
|
|
|
|
Hi,
It may sound weird but if you want to trap the TAB key for a control
then you should check it in the KeyUp event of the next control(Next Control : control is getting focuse On pressing Tab)
|
|
|
|
|
Hi,
AFAIK you should override IsInputKey().
|
|
|
|
|
Hello Luc,
I also tried it, because I'm currious, but sadly it doesn't jump in the overriden method.
Tried it in the MainForm and in an UserControl.
protected override bool IsInputKey(Keys keyData)
{
return base.IsInputKey (keyData);
}
I read the msdn infos and know how it should work, but now I'm confused?
Any hints?
All the best and mercy,
Marin
-- modified at 11:45 Wednesday 28th February, 2007
Ok, just found out how to use it in an inherit TextBox for example:
protected override bool IsInputKey( System.Windows.Forms.Keys keyData )
{
switch ( keyData)
{
case Keys.Tab:
return true;
default:
return base.IsInputKey(keyData);
}
}
But it's not working on an UserControl or Form.
All the best,
Martin
|
|
|
|
|
Hi Martin,
Martin# wrote: But it's not working on an UserControl or Form.
What do you mean by this ? Is your IsInputKey() not called at all ? (for regular chars,
for TAB, arrows...) ? or is its return value simply ignored ?
And for which .NET version is this observation ?
I am using IsInputKey() on Panels only (both 1.1 and 2.0), no problem there.
|
|
|
|
|
Luc Pattyn wrote: s your IsInputKey() not called at all ? (for regular chars,
for TAB, arrows...) ?
Yes, in all points!
-- modified at 14:12 Wednesday February, 2007
I'm just rereading what I was answering before.
I think it was not clear.
What I meant, was that it is never called!
-- modified at 5:09 Thursday 1st March, 2007
I'm only using 1.1
|
|
|
|
|
I tried it too,
I override the IsInputKey method for the FORM, and the method was not called.
According to MSDN, it should be called.....
|
|
|
|
|
I have a weird problem. I have a VERY simple application that has been associated with a extension of .tix on my computer. Basically I want it when I open this .tix file, it sends the contents of the file thru the serial port. All the application has to do is send the data, and then close so there is no need for a form or anything else. What I have done is created a simple desktop application and in the Program.cs file I changed it to the following code. Just for testing I have hard coded in the contents of the .tix file into the variable TicketText. In Visual Studio when I run the application in debug mode I get a MessageBox that says "Ticket Printed-" and the application closes. The information is sent correctly thru the Serial Port as it should. When I load a .tix file then nothing is sent to the serial port. What is the difference?
<br />
static void Main(string[] args)<br />
{<br />
string TicketFileName = ""; <br />
try<br />
{<br />
TicketFileName = args[0].ToString();<br />
}<br />
catch { }<br />
<br />
SerialPort sp = new SerialPort();<br />
<br />
string TicketText = "Brad Presents BX3";<br />
<br />
sp.PortName = "COM4";<br />
sp.BaudRate = 1200;<br />
sp.Parity = Parity.None;<br />
sp.DataBits = 8;<br />
<br />
sp.Open();<br />
sp.WriteLine(TicketText);<br />
sp.Close();<br />
<br />
MessageBox.Show("Ticket Printed-" + TicketFileName.ToString());<br />
<br />
Application.Exit();<br />
}<br />
|
|
|
|
|
Brad Wick wrote: When I load a .tix file then nothing is sent to the serial port. What is the difference?
Hard or even impossible to say without seeing the code that loads the file.
"Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the Universe trying to produce bigger and better idiots. So far, the Universe is winning." - Rick Cook www.troschuetz.de
|
|
|
|
|
Hi,
it is in general a bad idea to ignore exceptions, which is what you do when specifying
an empty catch block. I suggest you put all your code in one try block, and
show the full exception.ToString() text in a messagebox when things go wrong (i.e.
inside the one and only catch block).
That will probably lead you straight to the heart of your problem.
|
|
|
|
|