|
DO NOT set Message.Result to FALSE like that! You could screw-up anything. You only set it when the message in which you're interested comes through the message handler. There are potentionally hundreds of messages flying through your message handler while initializing, with many more passing through while the code is executing or even idle in some cases.
See my sample code that I posted which does work. I also mentioned that I mis-read the documentation - you actually pass TRUE (new IntPtr(1) ) to deny changing the column header width.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Actually, I have that backward: return TRUE to deny changes or FALSE to allow them. My bad. Also, something in base.WndProc is resetting the Message.Result back to 0, so you will have to call it first. Since I made a mistake, I'll post my modified source here:
using System;
using System.Drawing;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Windows.Forms;
[assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyKeyFile(@"C:\Proplanner.NET\KeyFile.snk")]
public class Test : Form
{
static void Main(string[] args)
{
bool b = true;
if (args.Length > 0)
{
try
{
b = bool.Parse(args[0]);
}
catch {}
}
Application.Run(new Test(b));
}
public Test(bool allowResizing)
{
SuspendLayout();
Text = "MyListView Test";
MyListView lv = new MyListView();
Controls.Add(lv);
lv.Dock = DockStyle.Fill;
lv.View = View.Details;
lv.AllowResizing = allowResizing;
lv.ColumnHeaderChanged += new ColumnHeaderChangedEventHandler(
lv_ColumnHeaderChanged);
ColumnHeader col1 = new ColumnHeader();
col1.Text = "One";
ColumnHeader col2 = new ColumnHeader();
col2.Text = "Two";
lv.Columns.Add(col1);
lv.Columns.Add(col2);
ResumeLayout();
}
private void lv_ColumnHeaderChanged(object sender,
ColumnHeaderChangedEventArgs e)
{
Console.WriteLine("Column {0} changed: new width = {1}",
e.ColumnHeader.Text, e.ColumnHeader.Width);
}
}
public class MyListView : ListView
{
private IntPtr hWndHeader;
private bool allowResizing = true;
public bool AllowResizing
{
get { return allowResizing; }
set { allowResizing = value; }
}
protected override void OnHandleCreated(EventArgs e)
{
base.OnHandleCreated(e);
hWndHeader = SendMessage(Handle, LVM_GETHEADER, 0, 0);
}
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
if (m.Msg == WM_NOTIFY)
{
NMHDR hdr = (NMHDR)Marshal.PtrToStructure(m.LParam, typeof(NMHDR));
if (hdr.hwndFrom == hWndHeader)
{
if (hdr.code == HDN_ITEMCHANGINGA ||
hdr.code == HDN_ITEMCHANGINGW)
{
if (allowResizing) m.Result = FALSE;
else m.Result = TRUE;
}
else if (hdr.code == HDN_ITEMCHANGEDA ||
hdr.code == HDN_ITEMCHANGEDW)
{
NMHEADER header = (NMHEADER)
Marshal.PtrToStructure(m.LParam, typeof(NMHEADER));
int index = header.iItem;
if (index >= 0 && index < Columns.Count)
{
ColumnHeader col = Columns[index];
OnColumnHeaderChanged(
new ColumnHeaderChangedEventArgs(col));
}
}
}
}
}
public event ColumnHeaderChangedEventHandler ColumnHeaderChanged;
protected virtual void OnColumnHeaderChanged(ColumnHeaderChangedEventArgs e)
{
if (ColumnHeaderChanged != null)
ColumnHeaderChanged(this, e);
}
private const int WM_NOTIFY = 78;
private const int HDN_ITEMCHANGINGA = -300;
private const int HDN_ITEMCHANGINGW = -320;
private const int HDN_ITEMCHANGEDA = -301;
private const int HDN_ITEMCHANGEDW = -321;
private const int LVM_GETHEADER = 4127;
private static readonly IntPtr FALSE = new IntPtr(0);
private static readonly IntPtr TRUE = new IntPtr(1);
[StructLayout(LayoutKind.Sequential)]
public class NMHDR
{
public IntPtr hwndFrom;
[MarshalAs(UnmanagedType.U4)] public int idFrom;
[MarshalAs(UnmanagedType.U4)] public int code;
}
[StructLayout(LayoutKind.Sequential)]
public class NMHEADER
{
public IntPtr hwndFrom;
[MarshalAs(UnmanagedType.U4)] public int idFrom;
[MarshalAs(UnmanagedType.U4)] public int code;
public int iItem;
public int iButton;
public IntPtr pitem;
}
[DllImport("user32.dll")]
private static extern IntPtr SendMessage(IntPtr hWnd, int msg,
int wParam, int lParam);
}
public delegate void ColumnHeaderChangedEventHandler(object sender,
ColumnHeaderChangedEventArgs e);
public class ColumnHeaderChangedEventArgs : EventArgs
{
private ColumnHeader columnHeader;
public ColumnHeaderChangedEventArgs(ColumnHeader header)
{
columnHeader = header;
}
public ColumnHeader ColumnHeader
{
get { return columnHeader; }
}
} To test this, copy it and compile it then run the application. As you can see you can resize the column headers. Now execute the program passing "false" as a command-line parameter and you'll see that you can't resize the column headers.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
I am working on the roosvelt ID3 algorithm and I want to know how to let the target node accept string and boolean attributes instead of only boolean attributes
Thanks
Cherif
P.S
an attached code will be very appreciated
|
|
|
|
|
Then declare it as an object property and validate that it is either a string or bool in the set accessor:
private object value;
public object Value
{
get { return this.value; }
set
{
if (value is string) this.value = value;
else
try
{
bool b = Convert.ToBoolean(value);
this.value = b;
}
catch
{
throw new ArgumentException("Invalid type.");
}
}
}
} If you want only boolean values (thus accepting values like "True" and "False" as strings), then declare the field (value in the example) as a bool but keep the property as an object . You can use Convert.ToBoolean or Boolean.Parse to convert a string to a boolean. If the string does not represent a boolean, then an exception is thrown (which you see I take advantage of in the example).
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
is there a way of changing the updatetext property of the update button in the editcommandcolumn in a datagrid at run time?
Thanks
|
|
|
|
|
Yes, but you may want to ask in the correct forum[^], or look at the EditCommandColumn.UpdateText property documentation in the .NET Framework SDK.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Obviously I am a newbie to programming. I need help with a windows form. I have created objects on the form and they are all working fine, but I would like to capture the return key and make it act like they clicked the OK button.
Thanks for the help,
Daniel
|
|
|
|
|
On your form in the designer, set it's AcceptButton property to the button your using for OK.
RageInTheMachine9532
|
|
|
|
|
In addition, you can set the DialogResult for that button to OK if you want it to return DialogResult.OK if you used ShowDialog on your Form . This also sets the Form.DialogResult property if you want to determine which button was clicked that closed the form (since setting the Form.DialogResult property also closes the Form ).
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
|
For .NET development - if you don't plan on supporting clients using other technologies - you may want to look at .NET Remoting instead. It is a much more powerful, more flexible technology and takes care of the communications automatically. The simplest designer just uses a shared assembly which defines interfaces that the server implements and that the clients user to communicate with the server through a proxy. When using the TcpChannel provided by the .NET Framework Class Library (FCL), you can even have events so that when a client sends a message to the server an event is raised and other clients can get the message immediately. If you're writing your own socket-based chat, you have to handle all this yourself.
In such a case, you need to keep track of connected clients (which .NET Remoting can also do for you pretty easily, though you could use something similar to...) by storing them in a list or something and associate them to each other were appropriate.
If you're having problems with the applications you've found on this site, then you should be specific about what those problems are and you should post questions on the articles' message boards since they're specific to that article.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Thank you Heart! Im gonna try the Remoting thing then
- Up The Irons, Morten Kristensen
|
|
|
|
|
Hi,
I'm writing a program based on an Access Database.
I need to create this database while installing the Application Installer.
While reading Visual Studio documentation, I saw I have to use the SQL Keyword CREATE DATABASE. This is ok for Sql Server, but not for Access.
How can I do ?
Any idea is welcome.
Thanks.
|
|
|
|
|
You either need to use DDL to create a database for Access, or just embed an empty .mdb (Jet Database) as an embedded resource in your assembly that contains the installer and just extract it (if you mean the Installer class). If you're using an installation package like Windows Installer (for which VS.NET contains a couple different projects for creating them), then you could just deploy an empty .mdb that way and put it wherever you need to.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Your right, the Jet engine doesn't know what to do with CREATE DATABASE...
Wouldn't it be alot easier to include a blank copy of your (database).MDB file with your installer?
RageInTheMachine9532
|
|
|
|
|
I have run into an issue in C# / .Net where the control box will not close the form when the user clicks on it.
When my app initially runs, it works fine, but after a while it does nothing when clicked on. I have multiple apps that act in this manner.
Has anyone else run into this? Is there a fix for it?
dpb
Darryl Borden
Principal IT Analyst
darryl.borden@elpaso.com
|
|
|
|
|
This commonly happens when a multi-threaded app has different threads setting properties on the controls that were created in a different thread, or when unhandled exceptions occur during instantiation of the main application form (the form used in the call to Application.Run ). First go through and make sure that you're handling all exceptions that could occur during instantiation of your child controls and that no worker threads are setting properties (and many times even getting properties) or calling methods on the controls from those threads (see Control.InvokeRequired and Control.Invoke in the .NET Framework SDK for more information).
A work-around is to use Application.Quit for your File->Exit (or whatever) menu instead of just calling Close on your form.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Hallo, my name is Axel. I´m in process of learning C#. and I want to realize the following problem:
- On a moblile computer runs a client, on my workstation a server application. I want to send simple commands from client to server. Depending on the received command the server application should do something (for example: open a picture, start internet explorer...)
- I want the server application to start once
so that the the client is (as often as necessary) able to connect/disconnect with the server to send data
- I've just tried a solution like the following, but it is not so good:
private void timer1_Tick(object sender, System.EventArgs e)
{
string[] Antwort = {"answer 1","answer 2","answer 3","answer 4"};
byte[] b = new byte[1];
Socket s = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
Socket sa;
try
{
s.Bind(new IPEndPoint(IPAddress.Any,65000));
s.Listen(1);
sa = s.Accept();
do
{
sa.Receive(b);
if (b[0] > 0)
{
this.statusBarServer.Text = "Server open";
if(b[0] <6)
{
this.statusBarServer.Text = "send back: "+ answer[b[0]-1];
sa.Send(Encoding.ASCII.GetBytes(answer[b[0]-1]));
}
else
sa.Send(Encoding.ASCII.GetBytes("wrong question"));
}
else
{
sa.Send(Encoding.ASCII.GetBytes("CU"));
}
}
while (b[0] >0);
sa.Close();
s.Close();
this.statusBarServer.Text = "Server close";
}
catch(SocketException ex)
{
this.statusBarServer.Text = ex.Message;
}
}
I don't like using a timer for this particular problem. Can someone give me any help?
Thanks,
Axel
|
|
|
|
|
Just have the server accept connections in a non-terminating loop. It gets the client Socket connection and spawns a new thread that handles the client communications. This is basically how all the major daemons work.
Also, you may want to look into .NET Remoting and host the remoting object either in a Windows Service or IIS. It's very flexible and very powerful, although it has a pretty steep learning curve if you're not familiar with it. It's definitely worth it, though, if you're developing distributed apps for the .NET Framework.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
What is wrong with writing a simple loop without closing the server down?
Or look into the Socket.BeginAccept method if you want something that will perform better.
If you don't kill me you will only make me stronger
That and a cup of coffee will get you 2 cups of coffee
|
|
|
|
|
Yeah, using a timer to start a listener is a REALLY bad idea. This will only try and start a new listener on every timer tick, even if the first one hasn't complete any kind of task. If your timer is launching a new listener every second, or even every minute, ... Uggggh, I don't even want to think about it...
RageInTheMachine9532
|
|
|
|
|
I've got a service that is dependent on some files, and checks for modification of the files (thanks to everyone who helped me understand how to do this). Now that I've got that done, I think it would be nice to be able to have another thread whose sole responsibility is to check the time stamp on these files and reload the data when needed, that way the users don't have to wait while data is reloadedl
My initial thought is to either create another thread and have it sleep or use timers to accomplish this, however I do not know where to place this code in my service. I don't think I would want to put it in the constructor otherwise it would get called whenever anyone made a request, and would result in mutliple threads doing the same thing. Is there anyway to create a new thread when the service starts up (before the initial request) that will do this?
Thanks for your help.
|
|
|
|
|
[edit]Doh. read web service as windows service. Please disregard. [/edit]
The system.timers.Timer is good for this. Add the timer to your service object. Then set the interval and assign the event in your constructor. Then you just need to start and stop the timer in your service start and stop events.
If you need to make absolutely sure that the timer will not be executing after you leave the stop event , you need to do your own thread syncronization, but in most cases you don't need to worry about it.
If you need to schedule multiple jobs look for the scheduled timer CP article I posted a few weeks ago.
If you don't kill me you will only make me stronger
That and a cup of coffee will get you 2 cups of coffee
|
|
|
|
|
I don't remember if you're the same guy I and nother guy were helping before, but look at the Cache class in the .NET Framework. You can access this in your Web Service using the Context property (HttpContext ), which gives you the Cache object. You can add a CacheDependency on that file so that if it changes the cached item is invalidated, so that you read-load the data.
If you look at the documentation for the Cache.Add method, however, you'd notice a CacheItemRemovedCallback parameter (the last parameter). If you didn't want to have the user wait until the data is reloaded, you could add a callback that loads the data as soon as the cache item is invalidated and removed from the cache.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Yes that was me, and thank you for your help. I've got the call back working to where it will remove the cached data on a change. However, in the method that does that, I also try to reload and then re-add the data, but it doesn't re-add.
Here is the method:
<br />
public void TPMDataRemovedCallback(String k, Object v, CacheItemRemovedReason r){<br />
TPMreason = r;<br />
string tpmDataKey = "TPMDATA";<br />
if(onTPMDataRemove == null)<br />
onTPMDataRemove = new CacheItemRemovedCallback (this.TPMDataRemovedCallback);<br />
DateTime NoAbsoluteExpiration = Cache.NoAbsoluteExpiration;<br />
TimeSpan NoSlidingExpiration = Cache.NoSlidingExpiration;<br />
CacheItemPriority Priority = CacheItemPriority.AboveNormal;<br />
Context.Cache.Remove(tpmDataKey);<br />
System.IO.FileInfo fileInfo = new System.IO.FileInfo(tpmFileName);<br />
tpmData = tpm.LoadTPM();<br />
try{<br />
Context.Cache.Add(tpmDataKey,this.tpmData,this.tpmDataCacheDependency,NoAbsoluteExpiration,NoSlidingExpiration,Priority,onTPMDataRemove);<br />
}<br />
catch(System.Exception caught){<br />
Console.WriteLine("Exception == " + caught);<br />
}<br />
}<br />
I don't see an exception get caught, but the cache at Context.Cache[tpmDataKey] doesn't contain anything. What am I doing wrong?
|
|
|
|