|
i've tried in the 2 ways, with ref TVITEM and Marshal but it doesnt work. the first two parameters are always 0 or undefined (using ref TVITEM).
i've declared the structure
<br />
[StructLayout(LayoutKind.Sequential)]<br />
public struct TVITEM<br />
{<br />
public IntPtr mask;<br />
public IntPtr hItem;<br />
public IntPtr state;<br />
public IntPtr stateMask;<br />
public IntPtr pszText;<br />
public IntPtr cchTextMax;<br />
public IntPtr iImage;<br />
public IntPtr iSelectedImage;<br />
public IntPtr cChildren;<br />
public IntPtr lParam;<br />
} <br />
<br />
my second test was with
<br />
public IntPtr Compare(IntPtr node1,IntPtr node2, IntPtr extraData)<br />
{<br />
TVITEM item1 = new TVITEM(); Marshal.PtrToStructure(node1, item1);<br />
TVITEM item2 = new TVITEM(); Marshal.PtrToStructure(node2, item2);<br />
TreeNode node_1 = TreeNode.FromHandle(this, item1.hItem);<br />
TreeNode node_2 = TreeNode.FromHandle(this, item2.hItem);<br />
but always the first 2 parameters are undefined. I've checked the value of extraData and it's correct, the same value i pass when call the sorting. I cant understand why the handle values of the 2 nodes are not passed to the callback function. However forcing the sorting of the two nodes, the tree updates correcly. But there's no way of testing the values of the 2 nodes.
I've created a little test application with only these things, and the behaviour is indentical
|
|
|
|
|
Are you passing a parent node when sending the TVM_SORTCHILDRENCB ? This should work.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
yeah, a node with 2 children ones. i've tested it with a messagebox and i'm sure it's the right node.
the function is
<br />
public void Sort(TreeNode parent, TreeViewSortCallback callback, bool ascending)<br />
{<br />
TVSORTCB sort = new TVSORTCB();<br />
sort.TreeItemHandle = parent.Handle;<br />
sort.Callback = callback;<br />
sort.ExtraData = new IntPtr(ascending ? 0 : 1);<br />
IntPtr hWnd = this.Handle;<br />
SendMessage(hWnd, 4373, IntPtr.Zero, ref sort);<br />
}<br />
I'm sure that it's the right call because, like i've said, i return -1 in the Compare function, the 2 nodes are inverted. Maybe there's some style of the TreeControl to set or similar?
|
|
|
|
|
No, there's not style to set. Again, read the documentation for the TVM_SORTCHILDRENCB [^] message and related topics linked in the page.
Upon further inspection, however, I noticed that the first two params are actually the lParam values of the TVITEM struct, which - believe it or not - is not set by the TreeNode.Tag property. You would have to override the TreeNodeCollection.Add(TreeNode) method with your derivative class and use new to override the Nodes property for both the TreeView and TreeNode classes to return your TreeNodeCollection derivative (they're not virtual ).
Your Add would be very similar to the current method, which you can see using .NET Reflector[^]. In fact, since some of those method calls are private or internal, you'll have to use base.Add(TreeNode) to get the index, and then global alloc the Tag to get an IntPtr then set the TVITEM using the TVM_SETITEM message.
You could do all this, or just sort the tree as I mentioned before yourself, which the TreeView class does instead of using the TVM_SORTCHILDREN message for the Tree-View common control.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
i've implemented the thing in this way:
<br />
[StructLayout(LayoutKind.Sequential)]<br />
public struct TVITEM<br />
{<br />
public int mask;<br />
public IntPtr hItem;<br />
public int state;<br />
public int stateMask;<br />
public IntPtr pszText;<br />
public IntPtr cchTextMax;<br />
public int iImage;<br />
public int iSelectedImage;<br />
public int cChildren;<br />
public int lParam;<br />
}<br />
<br />
class myTreeNode : TreeNode<br />
{<br />
public Int32 ItemType;<br />
public const int TV_FIRST = 0x1100 ;<br />
public const int TVM_GETITEM = TV_FIRST + 62 ; <br />
public const int TVM_SETITEM = TV_FIRST + 63 ;<br />
<br />
public Int32 item_type<br />
{<br />
set<br />
{<br />
this.ItemType = value;<br />
<br />
TVITEM item = new TVITEM();<br />
SendMessage(this.Handle, TVM_GETITEM, new IntPtr(0), ref item);<br />
item.lParam = value;<br />
SendMessage(this.Handle, TVM_SETITEM, new IntPtr(0), ref item);<br />
}<br />
get<br />
{<br />
return this.ItemType;<br />
}<br />
}<br />
<br />
[DllImport("user32.dll")]<br />
private static extern IntPtr SendMessage(<br />
IntPtr hWnd,<br />
[MarshalAs(UnmanagedType.U4)] int msg,<br />
IntPtr wParam,<br />
ref TVITEM item);<br />
<br />
after adding the node in the TreeView i set the item_type value with my number, and it automatically set the TVITEM lParam value. the problem is that TVM_GETITEM and TVM_SETITEM messages seem to not work the TVITEM is not filled but the first message, and the second doesnt set any values in the node. Is the TVITEM structure correct? i've tried also to declared all its properties to IntPtr but with no improvements.
|
|
|
|
|
There are actually two sets of TVM_GETITEM and TVM_SETITEM message for ASCII and Unicode, if you look at the CommCtrl.h:
private const int TV_FIRST = 0x1100;
private const int TVM_GETITEMA = TV_FIRST + 12;
private const int TVM_GETITEMW = TV_FIRST + 62;
private const int TVM_SETITEMA = TV_FIRST + 13;
private const int TVM_SETITEMW = TV_FIRST + 63; You need to send the message appropriate to the Windows platform you're running on:
int msg = TVM_SETITEMA;
if (Environment.OSVersion.Platform == PlatformID.Win32NT ||
Environment.OSVersion.Platform == PlatformID.WinCE)
msg = TVM_SETITEMW;
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
with both the two set of messages there's no retrieval of the TVITEM data and setting of my TVITEM data. It's always 0 all
It's hard to think it maybe work
|
|
|
|
|
I found the following in "winuser.h".
/*
* Move Size
* EVENT_SYSTEM_MOVESIZESTART
* EVENT_SYSTEM_MOVESIZEEND
* Sent when a window enters and leaves move-size dragging mode.
*/
#define EVENT_SYSTEM_MOVESIZESTART 0x000A
#define EVENT_SYSTEM_MOVESIZEEND 0x000B
I would like to know when the movesizeend event occurs. Can you show me some code on how to utilize this? I'm at a loss.
|
|
|
|
|
In your form, override the WndProc method.
You'll then have to check for message sent, if you need to know the message value, use the Spy++ tool to spy on the messages (and their corresponding message values) that are being sent to your app.
That said, there's probably managed events already raised for you, no need to dig into Win32. What exactly are you trying to accomplish? If you're trying to know when the form or some control has been resized, for example, managed events are already raised for you, and are much easier to implement handlers for.
#include "witty_sig.h"
|
|
|
|
|
That won't work. Those are notification messages sent by the accessibility APIs and require a callback installed by SetWinEventHook .
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
You have to P/Invoke SetWinEventHook (and later unhook it with UnhookWinEvent ) and handle those messages. Here's something I threw together quickly:
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows.Forms;
public class Test
{
static void Main(string[] args)
{
using (AccessibleForm form = new AccessibleForm())
{
form.MoveSizeStart += new EventHandler(OnMoveSizeStart);
form.MoveSizeEnd += new EventHandler(OnMoveSizeEnd);
Application.Run(form);
}
}
static void OnMoveSizeStart(object sender, EventArgs e)
{
Console.WriteLine("Move/Size has started.");
}
static void OnMoveSizeEnd(object sender, EventArgs e)
{
Console.WriteLine("Move/Size has ended.");
}
private class AccessibleForm : Form
{
private GCHandle cbHandle;
private IntPtr hWinEventHook;
public AccessibleForm()
{
WinEventProcCallback callback =
new WinEventProcCallback(WinEventProc);
cbHandle = GCHandle.Alloc(callback);
hWinEventHook = SetWinEventHook(
new IntPtr(EVENT_SYSTEM_MOVESIZESTART),
new IntPtr(EVENT_SYSTEM_MOVESIZEEND),
IntPtr.Zero,
(IntPtr)cbHandle,
Process.GetCurrentProcess().Id,
0,
new IntPtr(1));
}
public event EventHandler MoveSizeStart;
public event EventHandler MoveSizeEnd;
protected override void Dispose(bool disposing)
{
if (hWinEventHook != IntPtr.Zero)
{
UnhookWinEvent(hWinEventHook);
hWinEventHook = IntPtr.Zero;
}
if (cbHandle.IsAllocated)
cbHandle.Free();
base.Dispose(disposing);
}
protected virtual void OnMoveSizeStart(EventArgs e)
{
if (MoveSizeStart != null)
MoveSizeStart(this, e);
}
protected virtual void OnMoveSizeEnd(EventArgs e)
{
if (MoveSizeEnd != null)
MoveSizeEnd(this, e);
}
private void WinEventProc(
IntPtr hWinEventHook,
uint evt,
IntPtr hwnd,
int idObject,
int idChild,
uint dwEventThread,
uint dwmsEventTime)
{
if (evt == EVENT_SYSTEM_MOVESIZESTART)
OnMoveSizeStart(EventArgs.Empty);
else if (evt == EVENT_SYSTEM_MOVESIZEEND)
OnMoveSizeEnd(EventArgs.Empty);
}
private const uint EVENT_SYSTEM_MOVESIZESTART = 0x000a;
private const uint EVENT_SYSTEM_MOVESIZEEND = 0x000b;
private delegate void WinEventProcCallback(
IntPtr hWinEventHook,
uint evt,
IntPtr hwnd,
int idObject,
int idChild,
uint dwEventThread,
uint dwmsEventTime);
[DllImport("user32.dll")]
private static extern IntPtr SetWinEventHook(
[MarshalAs(UnmanagedType.SysUInt)] IntPtr eventMin,
[MarshalAs(UnmanagedType.SysUInt)] IntPtr eventMax,
IntPtr hmodWinEventProc,
IntPtr lpfnWinEventProc,
[MarshalAs(UnmanagedType.U4)] int idProcess,
[MarshalAs(UnmanagedType.U4)] int idThread,
[MarshalAs(UnmanagedType.SysUInt)] IntPtr dwflags);
[DllImport("user32.dll")]
private static extern bool UnhookWinEvent(IntPtr hWinEventHook);
}
} The problem is that in-context hooks require the callback to be in a native DLL to be mapped into the process. Out-of-context hooks marshal across process boundaries but we're in the same process.
If all you're trying to do is get notification when a user moves a window, handle the LocationChanged event and use a timer (like the Windows Forms Timer component you'll find in the toolbox). The timer is initially stopped. In your LocationChanged event handler, start the timer. With each call to the handler (there will be many), increment the Timer.Interval by 500 ms or so. When the timer's Tick event handler is called, stop the timer and perform the operations you want. Also reset the Interval back down to its default, like 500 (.5 seconds).
Timers are used like this for many different things, including click vs. double-click. There's other ways to do this as well, but this is just one idea.
Also, relying on accessibility (in which those notification messages relate) is probably not a good idea since it's not very portable.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Thanks, I think the timer idea will work. I thought about using a timer but I seem to be brain dead this week and couldn't think how to implement it. You are my hero. Thanks again!!!!!
|
|
|
|
|
Hi,
I want to dynamically allocate datagrids depending on the input. So I declared a datagrid array .But it is not working . Can I do this way?
KArteek
|
|
|
|
|
Hi,
I want to display the tables in a database in a C# form graphically. I want to use a datagrid to fill the schema of each table. Is there any other way to represent graphically a table. Now I want to show foreign key relationships between the tables. How do I show it graphically .
Then I should be able to move the tables and the relations between them also should move..
What controls should I use to get the above thing done and how to use it?
Karteek
|
|
|
|
|
Not in the .NET FCL, no. There might be some custom controls you can use in your software - either free or commercial - on the 'net (I know that some applications have such capabilities, but they're typically stand-alone applications or add-ins specific to a product). Just google. Otherwise, you'll need to create your own implementation.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
HI,
I did not find any .If u find please tell me. What if I want to create my own one?
Karteek
|
|
|
|
|
This forum is for asking specific questions, not about designing an entire control or application. The place to start is learning about custom graphics, owner-drawn controls, and the like. There are articles about such topics here on CodeProject and the rest of the 'net.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
hai there
i have a horscroll bar and a vertical on my form. user may clck once or twice or n number of continues time with out releasing the mouse( click and hold);
i need to cancel all click event and i need to take the last click event.
that is if he click and hold the mouse i need to find the last click value and no of click made on that holding process.
how it is possible
Sreejith S S Nair
|
|
|
|
|
Be patient. I already answered your post you made just a short while ago.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Hello!
I need some help here. I have this appliaction where i can load textfiles and decrypt/encrypt with DES cryptation. The problem is how i should know what files are already encrypted at load? if they are, you should be prompted for a password to unlock it, else it should just load the file.. both ways works if i know before i load the file if it's encrypted or not (i can set wich loadfunction to be used programmaticlly then). I need to be able to choose another loadfunction if the file is encrypted. So, how do i check if the file is encrypted or not? I had an idea to check for chars not in the asciitable.. but it doesnt seem to work.. anyone with some good ideas?
thanks!
|
|
|
|
|
It's not possible to detect if it has been encrypted. The ASCII-table method does not work if someone wants to encrypt a binary file for example.
Your best bet will be to change the file extension on encryption and detect encrypted files according to the extension. Say you have a file "secrect.doc". On encryption, your application could rename it to "secret.doc.enc". When the user wants to decrypt files, he can be displayed only those files that have the extension .enc.
HTH. Greets,
Daniel
---
SharpPrivacy - A free OpenPGP Implementation in c#
http://sharpprivacy.sf.net
|
|
|
|
|
Good idea (and typical, which I'm sure you already know since you seem to be involved with PGP - cool!), except he did state he is encrypting text files (or "textfiles" as he said). In such a case, you could read the few bytes (since the first 2 bytes could be a byte order mark, or BOM) or take a random sampling (several characters from different locations) and see how many are in the printable ASCII range. For Unicode files, you'd have to take this a step further and use the StringInfo class to get text elements, if possible.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Uuups, I overread the text file part. Anyway, I still think that the file extension way is the most practical. He could also use statistical analysis (simply count the number of occurances per byte. the resulting graph will be almost equally spread for encrypted files and will have peaks for other files [will work with most binary filetypes too, but not with compressed files]).
Greets,
Daniel
---
SharpPrivacy - A free OpenPGP Implementation in c#
http://sharpprivacy.sf.net
|
|
|
|
|
Oh, don't get me wrong, I completely agree with you about using different extensions. I use PGP* and X.509 certs a lot myself so I'm definitely stranger to it. I was just offering a slightly different alternative.
* Is your OpenPGP implementation derivative of the crypto classes in System.Security.Cryptography ? I really don't have the time to check it out right now, so I was just wondering.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Did not get you wrong . No offence taken, none intended
Ad *:
No it's not. OpenPGP uses a /really/ strange cipher mode for symmetrical ciphers that is not supported by SSC. I took the (open source) implementation from the Mono project and modified it accordingly. The asymmentrical ciphers are also from Mono, for coherancy (spelling?) reasons.
Greets,
Daniel
---
SharpPrivacy - A free OpenPGP Implementation in c#
http://sharpprivacy.sf.net
|
|
|
|
|