|
The fact that the number looks negative to you doesn't mean it's negative to a CPU. The runtime doesn't really care, either, except when it comes time to compare or display the value. The Type of the value type will determine if it can be negative or not.
A 32-bit signed integer such as -552 is the same as the 32-bit unsigned integer 0xfffffdd8. When taking into account unsigned equivalents, this is 4294966744.
Unfortunately, this only would've applied if the const was defined as a UInt32 (uint keyword). Sorry about the confusion. Instead, define your constant int as the hex value given above and it should work.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Please forgive me if I'm being exceptionally dense, but it's still not clear to me.
Heath Stewart wrote:
A 32-bit signed integer such as -552 is the same as the 32-bit unsigned integer 0xfffffdd8. When taking into account unsigned equivalents, this is 4294966744.
Thank you for explaining this. This part makes perfect sense to me, that's not the problem.
The range for TabControl messages, according to CommCtrl.h is -550 to -580. None of the value I get from my tab control is even close to this range. Switching back and forth between pages, selecting controls on the pages, hiding and showing the form... all of them return message IDs of 0-675
Heath Stewart wrote:
define your constant int as the hex value given above and it should work.
I can't do this because 0xffffdd8 is beyond the valid range of values for an int . Using a long or unit would be pointless because the Msg poperty of Message is of type int .
const int TCN_SELCHANGING = -552;
protected override void WndProc(ref Message m) {
Debug.Assert(m.Msg != TCN_SELCHANGING);
base.WndProc (ref m);
}
|
|
|
|
|
It wouldn't be pointless to define a uint because you can always cast it to an int upon comparing, but I wouldn't recommend it since this method should be fast (it has to process potentially a lot of messages, after all) and the extra instruction to cast (and possibly two more to store and retrieve depending on the code) is too expensive.
Fortunately, I re-read the documentation for TCN_SELCHANGING and noticed that this message is sent in the form of a WM_NOTIFY message to the parent of the TabControl . This little example works:
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
public class Test : Form
{
public static void Main()
{
Application.Run(new Test());
}
public Test()
{
TabControl tab = new TabControl();
this.SuspendLayout();
this.Text = "Test";
this.Controls.Add(tab);
tab.TabPages.Add(new TabPage("Page 1"));
tab.TabPages.Add(new TabPage("Page 2"));
tab.Dock = DockStyle.Fill;
this.ResumeLayout();
}
private const int WM_NOTIFY = 0x004e;
private const int TCN_SELCHANGING = -552;
private struct NMHDR
{
public IntPtr hwndFrom;
public int idFrom;
public int code;
}
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));
Console.WriteLine(hdr.code);
if (hdr.code == TCN_SELCHANGING)
m.Result = new IntPtr(1);
}
}
} Sorry for the mess. Most messages I deal with are sent directly and aren't WM_NOTIFY style messages. This gets a little quirky. You'll notice I marshal the LPARAM parameter to an NMHDR struct, which I then check the code. Getting to know the notification messages helps, I just feel dumb that I didn't fully read it before.
Also note that I'm calling base.WndProc first. If you don't, Windows is likely to change the Message.Result field to 0 (or reset it to 0). You could also just not call it and return in this case if you get the WM_NOTIFY message with the NMHDR.code set to TCN_SELCHANGING .
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
That is a beautiful thing.
I started programming with .NET and have always been somewhat uncomfortable when it comes to anything outside the framework, although I am reasonably adept at programming within it.
Thank you, Heath, for your help. It's a small thing, I know, but it helped me tremendously.
|
|
|
|
|
Hi.
I just tried this and it works just fine. Great
However, it is still possible to change the tab by pressing the default shortcutkey (ctrl + tab).
I want to be able to control this too. My guess is that all I have to do is add a check do compare to a different messagenumber. Is this correct? If so, Do you have a link to som docs where I can find this number?
I would also like to know if it is possible to detect which tabpage he pressed. for example:
If the user is on tabpage1, he can go to tabpage 2 but NOT to tabpage 3.
To be able to do this, I need to know which tabpage he clicked
Thanks so far.
|
|
|
|
|
As with all Windows Common Controls, you can find these in the Platform SDK on MSDN Library Online[^]. For the common controls, see http://msdn.microsoft.com/library/en-us/shellcc/platform/commctls/wincontrols.asp[^]. Under "Individual Controls" you'll find documentation on the control messages you want. You should take a look at the rest of the stuff, too.
You can try overriding OnKeyDown , although IIRC Ctrl+Tab is handled a little differently. You can find more information about handling the notification messages in the application pump (using an IMessageFilter perhaps) if this is the case in the .NET Framework SDK (find the interface in the help index I mentioned) and in the Platform SDK.
In order to determine which tab he clicked on, you're going to have to do a lot of this yourself. You can override the OnMouseDown event which gives you coordinates relative to the client (TabControl ). Then enumerate your TabPage s and call TabControl.GetTabRect with each one (or rather, their index) and use Rectangle.Contains to see which they clicked on. Other ways most likely won't work because you stopped the tabs from changing, so the other messages that fire events in .NET won't be sent and received.
In cases when you derive a control, you should override the OnEvent method, calling base.OnEvent before or after your code (depending on the circumstances). Handle these events from outside the class. This improves performance slightly and makes for a better polymorphic design.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
How can I in my winform display picture or icons in one of the columns in my datagrid?
|
|
|
|
|
By writing your own DataGridColumnStyle class. There are many examples out there that describe hosting a ComboBox in a DataGridColumnStyle , and these wouldn't be hard to adapt and use a PictureBox instead. If you want, you wouldn't even have to worry about the editing if you want this image to be read-only (the editing is the most difficult part). Just make sure your query returns a BLOB (which you can read into a Stream , like a MemoryStream ) or a path to an image.
For a good example of hosting a ComboBox in a DataGridColumnStyle , see http://msdn.microsoft.com/msdnmag/issues/03/08/DataGrids/[^]. It includes examples and sample source.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
hi,
table containing fileds code,name. in the name field i need query to retrive repeated datas and code is not same. any one help to me. thanks in advance.
Have A Nice Day!
Murali.M
|
|
|
|
|
|
<br />
private void btnAddP_Click(object sender, System.EventArgs e)<br />
{<br />
<br />
try<br />
{<br />
createSqlConnection();<br />
<br />
if ( txtName.Text != "" && txtHPNO.Text != "")<br />
{<br />
myCommand = new SqlCommand("INSERT INTO Patient(Acct ID, Name, Age, Height, Weight, Address, IcNo, HomeNo, HpNo, EName, EPhoneNo, ERelation, Date, Status, Remarks) VALUES('"+@txtAcctId.Text+"','"+@txtName.Text+"','"+@txtAge.Text+"','"+@txtHeight.Text+"','"+@txtWeight.Text+"','"+@txtAdd.Text="','"+@txtICNO.Text+"','"+@txtHomeNo.Text+"','"+@txtHPNO.Text+"','"+@txtEName.Text+"','"+@txtEPhoneNo.Text+"','"+@txtERelation.Text+"','"+@dTimeDate.Text+"','"+@txtStatus.Text+"','"+@txtRemarks.Text+"')",myConnection);<br />
<br />
MessageBox.Show("Creating New Patient Record.....", "Information");<br />
<br />
myCommand.ExecuteNonQuery();<br />
<br />
MessageBox.Show("New Patient Record Created","Information");<br />
<br />
myConnection.Close();<br />
}<br />
<br />
else<br />
{<br />
MessageBox.Show("All Text Boxes Should be Filled with Information","Reminder");<br />
}<br />
}<br />
<br />
catch (Exception error1)<br />
{<br />
MessageBox.Show(error1.ToString());<br />
}<br />
when i compile the .cs file i get an error..can anyone tell me whats wrong
D:\ASGill\D E G R E E\D. Final Year Project (7)\SOFTWARE\C.I.System\CLINICINFORMATIONSYSTEM\AddPatient.cs(534): The left-hand side of an assignment must be a variable, property or indexer
what does it mean?...
thx
Arvinder Gill
|
|
|
|
|
|
Didn't I tell you before that you shouldn't use string concatenation for SQL queries? What in the hell do you think the OleDbParameter and SqlParameter are for? ADO.NET introduces parameterized expressions which take ALL of the encoding work out of your application. Got a quote in one of your variables? With your way, you have to parse your values and make sure they quotes are escaped or encoded. With parameterized queries, you don't have to worry about it. Besides, massive string concatenation like you're doing is a drastic performance decrease, resulting in (m-1)O(2n) times where m is the number of strings and n is the characters in each string.
See the OleDbParameter[^] class documentation in the .NET Framework SDK for more information and an example. Most likely, not escaping or encoding your string values is what's causing that error since the string is generated and sent to the database engine AS IS.
Also, don't prompt the user before executing the query! First of all, it's annoying. Second of all, if you open the connection before prompting and they don't respond for a while (why would they think they need to answer such a stupid dialog - no other program does it; they just work). The connection gets closed and your call to ExecuteNonQuery throws an exception. Also, put your connection.Close in the finally block to make sure it gets closed on success or failure (exception). Microsoft has recommended this time and time again if you actually read the .NET Framework SDK. The finally block will always run regardless of whether or not an exception was thrown (always except for when Environment.Exit is called, which unloads the CLR - and your application - immediately).
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Hi,
I've created a custom control that inherits from ListBox, it has custom draw enabled so i can make it look almost exactly like the Outlook 2003 Inbox Listbox.
Currently i add my "Objects" to the list using the standard "Add" function in the "ListBox.ObjectCollection", however this forces me to do a type check when drawing as anything can still be added to the collection.
Ideally i would like to override the "Add" function described above to force only my "Objects" to be added, but i can't find any documentation on how to go about this.
Any example or pointer would be great to finish my control off.
Thanks in advance
|
|
|
|
|
You have to hide that member by using the new operator, which only makes it valid when the variable type is your custom ListBox derivative class:
public class MyListBox : ListBox
{
private MyListBox.MyObjectCollection items;
public new MyListBox.MyObjectCollection Items
{
if (items == null)
items = new MyListBox.MyObjectCollection();
return items;
}
private class MyObjectCollection : CollectionBase
{
}
}
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Hi.
I just found the wonderfull SuspendLayout Method on the WinForm class.
I was wondering if there is a similar feature to susoend the layout for the whole Application in multible forms, without doing it on every single form?
Something like Application.SuspendLayout();;)
Any ideas or suggestions?
|
|
|
|
|
No, and why would there be? The whole idea of object-oriented programming is that objects are responsible for themselves (encapsulation, data hiding, etc.). Each form initializes it's surface so you just need to suspend and resume the layout in each. An Application in Windows Forms really just represents the message pump that keeps the main window (Form ) alive and dispatches window messages to their respective windows.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
I have a Form containing a Panel that contains buttons.
The size of the panel will sometimes change, and I whant the bounds of the buttons to change acordenly to the panel.
Is there a method for this, or must I recalculate the bounds of all the buttons each time?
(Maybe something like setting the panel as the buttons parent)
Thanks
Thomas
|
|
|
|
|
The controls can automatically be resized, but they can't move in relation to an adjacent control's size automatically. For information on what is possible, see the Control.Anchor and Control.Dock property documentation in the .NET Framework SDK. These are exposed in the Visual Studio .NET designer as well.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Heath:
This is the second time someone asks a question like this. Simply point them to the code I posted (see post below this one).
This is a typical question from programmers that used a third party VB control, and that I believe is not available for .NET.
FYI: I know that the code posted does not work nicely with text boxes (for which I have a private solution), but it should give them a starting point to work from.
|
|
|
|
|
Second? Yeah right - try 200th. Instead of harping on me though, why don't you harp on the original posters for not searching previous forum threads BEFORE posting their (most-likely) previously-asked questions?
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Heath:
Not harping on you, nor the original poster. Repetition is the unfortunte by-product of support, which you seem to do more than your share on this board.
|
|
|
|
|
using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Windows.Forms;
namespace Workbench
{
/// <summary>
/// A panel that resizes controls automatically.
/// </summary>
public class AutoSizePanel : Panel
{
/// <summary>
/// Holds the control info.
/// </summary>
private Hashtable htInfo = new Hashtable();
/// <summary>
/// Flag to prevent recursive call.
/// </summary>
private bool bAllowResize = true;
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.Container components = null;
/// <summary>
/// Constructor.
/// </summary>
public AutoSizePanel()
{
InitializeComponent();
}
/// <summary>
/// Adds a control to the list of controls.
/// </summary>
/// <param name="e"></param>
protected override void OnControlAdded(ControlEventArgs e)
{
// Hold the resizing
bAllowResize = false;
// Create the original info
SizingInfo riData = new SizingInfo(e.Control);
// Add to table
htInfo.Add(e.Control, riData);
// BAck to normal
bAllowResize = true;
//
base.OnControlAdded (e);
}
/// <summary>
/// Removes a control from the list of controls.
/// </summary>
/// <param name="e"></param>
protected override void OnControlRemoved(ControlEventArgs e)
{
// Delete the info
htInfo.Remove(e.Control);
//
base.OnControlRemoved (e);
}
/// <summary>
/// Does the magic.
/// </summary>
/// <param name="e"></param>
protected override void OnResize(EventArgs e)
{
// Only once
if (bAllowResize)
{
// Set
bAllowResize = false;
// And apply to each control
foreach (Control ctl in this.Controls)
{
// Get the original info
SizingInfo riCtl = htInfo[ctl] as SizingInfo;
// Info available?
if (riCtl != null)
{
// Resize
riCtl.Resize(ctl);
}
}
// Reset
bAllowResize = true;
}
//
base.OnResize (e);
}
protected override void OnPaint(PaintEventArgs e)
{
// Hold the resizing
bAllowResize = false;
// Collect info
foreach (Control ctl in this.Controls)
{
// Get the original info
SizingInfo riCtl = htInfo[ctl] as SizingInfo;
// Info available?
if (riCtl != null)
{
// Update
riCtl.Update(ctl);
}
}
// Back to normal
bAllowResize = true;
//
base.OnPaint (e);
}
/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if(components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
//
// AutoSizePanel
//
this.Name = "AutoSizePanel";
this.Size = new System.Drawing.Size(232, 184);
}
#endregion
/// <summary>
/// This holds the original control information.
/// </summary>
private class SizingInfo
{
/// <summary>
/// Info to be kept.
/// </summary>
public int iTop;
public int iLeft;
public int iHeight;
public int iWidth;
public int iParentHeight;
public int iParentWidth;
/// <summary>
/// Constructor
/// </summary>
/// <param name="ctl"></param>
public SizingInfo(Control ctl)
{
// Save
this.Initialize(ctl);
}
/// <summary>
/// Updates the internal info
/// </summary>
/// <param name="ctl"></param>
public void Update(Control ctl)
{
// Compute the change.
double dRatioHeight = (double) ctl.Parent.Height / iParentHeight;
double dRatioWidth = (double) ctl.Parent.Width / iParentWidth;
// And where it would go.
int iWTop = (int) (iTop * dRatioHeight);
int iWHeight = (int) (iHeight * dRatioHeight);
int iWLeft = (int) (iLeft * dRatioWidth);
int iWWidth = (int) (iWidth * dRatioWidth);
// Changes?
if ((iWTop != ctl.Top) || (iWLeft != ctl.Left) || (iWHeight != ctl.Height) || (iWWidth != ctl.Width))
{
// Reset
this.Initialize(ctl);
}
}
/// <summary>
/// Does the magic
/// </summary>
/// <param name="ctl"></param>
public void Resize(Control ctl)
{
// Compute the change.
double dRatioHeight = (double) ctl.Parent.Height / iParentHeight;
double dRatioWidth = (double) ctl.Parent.Width / iParentWidth;
// And shake it
ctl.Top = (int) (iTop * dRatioHeight);
ctl.Height = (int) (iHeight * dRatioHeight);
ctl.Left = (int) (iLeft * dRatioWidth);
ctl.Width = (int) (iWidth * dRatioWidth);
}
/// <summary>
/// Saves the base info
/// </summary>
/// <param name="ctl"></param>
private void Initialize(Control ctl)
{
// Save
iTop = ctl.Top;
iLeft = ctl.Left;
iHeight = ctl.Height;
iWidth = ctl.Width;
iParentHeight = ctl.Parent.Height;
iParentWidth = ctl.Parent.Width;
}
}
}
}
|
|
|
|
|
I used the "Abort()" method of class Thread in a program to cancel a thread. It seemed to function correctly, but after the main program exited, the process can still be found in processes tab of "Windows Task Manager". Whenever this line is not executed, the problem does not occur.
Is it inappropriate to cancel a thread in this manner?
|
|
|
|
|
1) Do you catch the ThreadAbortException in a loop like that?
try{<br />
for(...){<br />
try{<br />
<br />
}catch{ ... }<br />
}<br />
}catch(ThreadAbortException){ ... }
Then the thread can run for hours without doing anything.
2) You can stop the thread a clean way. Declare a boolean variable, and check it's value in the thread method:
bool threadStopped = false;<br />
...<br />
private void myThreadMethod(){<br />
doSomething();<br />
if(stopped){ return; }<br />
doSomethingElse();<br />
if(stopped){ return; }<br />
doAnything();<br />
if(stopped){ return; }<br />
...<br />
}
With that stop-variable you don't need Thread.Abort() and the try/catch stuff, because the thread stops when you set threadStopped = true .
|
|
|
|
|