|
This is not exactly related to C#, sorry for the same.
The situation is, I have written a class in C#(say root.cs), if some one uses it, I want to compel the user to call 2 public methods (out of say 20 public methods written in root.cs) that he must call inorder to make the correct use of roor.cs
please guide
|
|
|
|
|
It's called a default constructor or static constructor. The static constructor runs once when the Type is first loaded, and the default constructor is (typically, depending on how you code your class) called when an instance is created:
public class Root
{
static Root()
{
}
public Root()
{
}
} If there are no other constructors or all parameterized constructors call the default constructor (add ": base()" after the constructor declaration), then there's no way the user can create the class without the default constructor being called (and there is absolutely no way for the static constructor not to be called if the Type is used).
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
I think my question was not written properly.
Let me explain it again.
I am trying to create/generate document in RTF format. I have written a small RTF write for the same. That has two important methods apart from several other methods.
1. CreateRTFHeader()
2. RTFEnd()
any one who wishesh to create RTF document must impliment method one at the begining(OR it can be called from the constructor with out expecting user to call it) and second method at the end.
But the second method call depends on user requirement, means the time he/she wants to conclude the document. If call is not given, the document remains syntactically imcomplete.
what to do in this situation? please guide
|
|
|
|
|
I think this is best addressed two ways:
1) Document how the person shoudl USE the library. If they don't do this, then that things will not work.
2) Use intrnal flags in the library that for example will not let you call RTFEnd unless you have first called CreateRTFHeader. It makes sense that you should be tracking some type of state internally if you are requiring the user to call things in a specific order.
There are two key rules here:
1) Tell the user how to use your code.
2) Do NOT rely on them doing what they are told.
Paul Watson wrote:
"At the end of the day it is what you produce that counts, not how many doctorates you have on the wall."
George Carlin wrote:
"Don't sweat the petty things, and don't pet the sweaty things."
Jörgen Sigvardsson wrote:
If the physicists find a universal theory describing the laws of universe, I'm sure the a**hole constant will be an integral part of that theory.
|
|
|
|
|
well said, very impressive
thanks/regards
|
|
|
|
|
You could implement the IDisposable interface and call RTFEnd (which isn't Pascal case, BTW; it should be RtfEnd to be CLS-compliant), but Ray is right: something require that you document what's required and hope people read it. If they don't, they shoot themselves in the foot.
This is not a rare request. Before executing a command in ADO.NET, a connection must be opened. Before writing to a file it must be closed. Etc. etc. You do what you can and leave it to the users to read the documents (and Ray is also right in implying that most won't - trust me). What can you do, though?
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Thanks for pointing out Case Problem, but it was my mistake in typing.;)
Well, for RtfHeader() I have used internal flag that is checked in every method that inserts either text or image. If its not been called, call it first.
Actually all methods return a string in RTF format, and the document is generated in the form that used Generator class by collecting all the strings that depends on user choise, thus I am not sure about how to impliment IDisposable fot RtfEnd().
tks/rgds
|
|
|
|
|
You implement IDisposable by, well, implementing IDisposable . It's just like any other object, and callers are suppose to call Dispose on any IDisposable implementation. Again, though, you can't force them (and doing this in the finalizer is not a good idea since the object could be finalized quite some time later).
You should implement IDisposable using the common approach:
public class RtfWriter
{
public RtfWriter()
{
RtfHeader();
}
~RtfWriter()
{
Dispose(false);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
RtfEnd();
}
}
void IDisposable.Dispose()
{
Dispose(true);
}
} On another side note, your naming convention isn't consistent. You should either define RtfHeader and RtfFooter , or define RtfBegin and RtfEnd . Naming conventions are valuable to boosting productivity. Microsoft's entire BCL naming convention is over 95% consistent according to FxCop. Anyone who recognizing the pattern and/or knows the naming convention will most likely be more productive; if there is no pattern, this point is moot.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Thanks for valuable multiple inputs. Actually I was also vacilating between the two names. As you know RTF is mainly divided in two parts, Header and Document Area, thats why I had written RtfHeader(), though it doesn't match with RtfEnd(). But now I've renamed it to RtfBegin(), thanks for clearing confusion
regards
|
|
|
|
|
what is the currect way of printing a printdocument using threads, does anyone have a code sample?
|
|
|
|
|
I'm trying to create a user control from the Button class, the problem is, is if I completely remove the code to do any drawing on the form and on the control(having empty onpaint and onpaintbackground methods in both), the control's client area is painted black... the problem is I am making a control that will use an alpha bitmap... and I have no idea why the form or control is doing this. I've looked at all the members of the class and tried to find something that would turn it off, but it doesn't... its very annoying :/ Anyways, heres the same code that demonstrates the problem for me:
[Form1.cs]
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
namespace WindowsApplication1
{
public class Form1 : System.Windows.Forms.Form
{
private System.ComponentModel.Container components = null;
private jButton jButton1 = new jButton();
public Form1()
{
this.jButton1.Location = new System.Drawing.Point(304, 216);
this.jButton1.Name = "jButton1";
this.jButton1.Size = new System.Drawing.Size(192, 176);
this.jButton1.TabIndex = 0;
this.jButton1.Text = "Blah Blah";
this.Controls.Add(this.jButton1);
}
[STAThread]
static void Main() { Application.Run(new Form1()); }
protected override void OnPaint(PaintEventArgs e) { }
protected override void OnPaintBackground(PaintEventArgs pevent) { }
} }
[jButton.cs]
using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Windows.Forms;
namespace WindowsApplication1
{
public class jButton : System.Windows.Forms.Button
{
public jButton() { }
protected override void OnPaint(PaintEventArgs e) { }
protected override void OnPaintBackground(PaintEventArgs pevent) { }
}
}
basically when I run this, I get a black box where the button is suppose to be.
|
|
|
|
|
Seems that if I set the BackColor to Transparent that it will not show it, which is a solution to the problem, but I wonder if the form is still drawing the client area... doesn't seem very optimal to draw behind something that will be overwritten anyways. Maybe with the transparency color it doesn't spend the time drawing anything? Oh well...
A second question is, is it possible to not have the button draw its border without stoping the call to the base.OnPaint(which draws the border in the first place)?
|
|
|
|
|
Hi
I creat new thread and run it:
System.Threading.ThreadStart st = new ThreadStart(MyRunig);<br />
tr = new Thread(st);<br />
tr.Name = "MyThread";<br />
tr.Start();
at MyRunig :
System.Windows.Forms.Application.Run();
so I have the new thread with window Q.
How can I send message from the main Thread (GUI) to the new one?
I used:
public void SendMyMessage()<br />
{ <br />
PostThreadMessage(fr.Handle,1122,(System.IntPtr)0,(System.IntPtr)0);<br />
}<br />
<br />
[DllImport("User32.dll")]<br />
public static extern bool PostThreadMessage( System.IntPtr idThread, int msgID,System.IntPtr pm,System.IntPtr lm);
But Ididn't get the message ( with WndProc )
Thanks
Koby
|
|
|
|
|
Hi Koby,
I've had a similar problem, and solved in in the following way:
1) I've got a class called, say, ThreadMessage. It provides methods for storing/retrieving all the required information
2) In the class that creates the thread I've got a stack of ThreadMessage objects, and methods for adding meassages to the stack
3) In the thread procedure I query if there are any messages in the stack, and if yes, I process them
Hope this helps
Regards,
Serge (Logic Software, Easy Projects .NET site)
|
|
|
|
|
Hi Serge
Thanks for your answer.
But in this solution I test the Q by time, and I am looking for Event driven mechanism.
Koby.
|
|
|
|
|
I have a plugin to Excel that works normally when excel is launched as a standalone application. However, when i open up excel in a dsoframer.ocx control, it does not enable the button. We have verified any discrepancies in our code.
My question is does the dsoframer control disable all plugins to the application or is there something that we are doing differently.
|
|
|
|
|
Hi All,
Has anybody implemented copying from excel and pasting on to Datagrid.
Thanks
Ruchi
|
|
|
|
|
This should work, I just threw it together so you will need to test it, but you should be able to get the idea.
IDataObject obj = Clipboard.GetDataObject();
DataTable table = new DataTable();
string data = string.Empty;
Char delim = ',';
if(obj.GetDataPresent(DataFormats.CommaSeparatedValue))
{
StreamReader reader = new StreamReader((Stream)obj.GetData(DataFormats.CommaSeparatedValue));
while(reader.Peek() > 0)
{
data = reader.ReadLine();
string[] arr = data.Split(delim);
if(table.Columns.Count <= 0)
{
for(int i = 0; i < arr.GetUpperBound(0);i++)
table.Columns.Add();
}
DataRow row = table.NewRow();
for(int j = 0; j < arr.GetUpperBound(0);j++)
{
row[j] = arr.GetValue(j);
}
table.Row.Add(row);
}
reader.Close();
dataGrid.DataSource = table.DefaultView();
}
- Nick Parker My Blog | My Articles
|
|
|
|
|
When you copy data in Excel, it uses several clipboard formats to store data (actually, quite a few more than "several"). Several of these will work, but your best bet is to use the "Csv" clipboard format):
IDataObject data = Clipboard.GetDataObject();
if (data != null)
{
string csv = data.GetData("Csv") as string;
if (csv != null)
{
using (StringReader reader = new StringReader(csv))
{
string line = null;
while ((line = reader.ReadLine()) != null)
}
}
} Where I've placed the comment you can either take the cheap way out and use line.Split(',').Trim('\"') , or parse it correctly by using a token reader. While there's no standard CSV format, the agreed-upon convention is to quote a field when the field value contains a comma (since the file is comma-delimited). So, when you encounter a quote set a flag (or increment a variable, whatever). When you encounter a comma, if the flag is set, then don't split the line. When you enounter the next quote, reset the flag. As long as that flag isn't set, you can split the field at the comma when you hit one.
There's other formats you can use as well. Excel 2003 copies the new standard Excel XML format to the clipboard, as well as many other formats (both text and binary formats).
You can use Mike Dunn's ClipSpy[^] to view the different formats, as well as the data those formats contain.
The real trick here is that you have to have some way to paste into the DataGrid . Once one of the cells is in edit mode, the DataGrid receives little to no notification; the control being hosted in the current cell is receiving notifications. You could either use a paste button or jump through hoops to support Ctrl+V (or the mouse) to paste into the DataGrid .
From there, it's as simple as the getting the data source (taking both DataSource and DataMember into account) and adding a new row/object for each line and, if applicable, each field in that row for each imported field from the CSV clipboard format.
And easy way is to use the CurrencyManager like so:
CurrencyManager cm = (CurrencyManager)dataGrid1.BindingContext[
dataGrid1.DataSource, dataGrid1.DataMember];
if (cm != null)
{
IList list = cm.List;
if (list is DataView)
{
DataTable dt = ((DataView)list).Table;
foreach ()
DataRow row = dt.LoadDataRow(line.Split(','), false);
}
}
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Im trying to repaint a window from handle.
I get its handle and call and API function
RedrawWindow, but it works half of the time.
The way its set up in my program. I have a global hook to mouse, on mouse move, my program gets the window handle to the window under mouse, from that handle i get device context, from dc I get the Graphics object and then paint a red rectangle over the window. Which works but in order to erase the rectangle when mouse is moved to a different window I have to cause the repaint event I presume.
I set that up, and the red rectangle gets "erased" about 30% of the time. I noticed only when I move the mouse to the lower edge of the screen and move it around then all rectangles get deleted. This is probably confusing so here is the code that needs help.
private void MovingMonitor(object sender, MouseEventArgs e)
{
//draws rectangle over point
//get handle of mouse over window
Point mousePoint = new Point(e.X,e.Y);
//get the window
IntPtr handle = USER32.GetAncestor(USER32.WindowFromPoint(mousePoint),2);
//get dc
IntPtr currentDC = USER32.GetWindowDC(handle);
if(stillWorking)
{
}
}
else
{
stillWorking = true;
if(lastHandle.Equals(handle))
{
testDraw = Graphics.FromHdc(currentDC);
//draw box around that window
USER32.Rect dcRect= new USER32.Rect();
USER32.Rect regionRect = new USER32.Rect();
USER32.GetWindowRect(handle,ref dcRect);
USER32.GetWindowRgnBox(handle,ref regionRect);
int width,height;
switch(USER32.GetWindowRgn(handle,GDI32.CreateRectRgn(0,0,0,0)))
{
case 0:
width = dcRect.x2 - dcRect.x1;
height = dcRect.y2 - dcRect.y1;
break;
case 2:
width = (dcRect.x2 - dcRect.x1)-(regionRect.x1+(dcRect.x2 - dcRect.x1)-regionRect.x2);
height = (dcRect.y2 - dcRect.y1)-(regionRect.y1+(dcRect.y2 - dcRect.y1)-regionRect.y2);
break;
case 3:
width = dcRect.x2 - dcRect.x1;
height = dcRect.y2 - dcRect.y1;
break;
default:
MessageBox.Show("Unexpected window style. Screencap may fail. Please e-mail pacemkr@optonline.net with details.",
"Warning!",MessageBoxButtons.OK,MessageBoxIcon.Warning);
width = dcRect.x2 - dcRect.x1;
height = dcRect.y2 - dcRect.y1;
break;
}
testDraw.DrawRectangle(new Pen(Color.Red,4),regionRect.x1,regionRect.y1,width,height);
}
else if(!(lastHandle.Equals(handle)))
{
//IntPtr lastDC = USER32.GetWindowDC(lastHandle);
//testDraw = Graphics.FromHdc(lastDC);
if(last!=0)
{
USER32.Rect dcRect= new USER32.Rect();
USER32.GetWindowRect(lastHandle,ref dcRect);
USER32.InvalidateRect(lastHandle, ref dcRect,false);
USER32.UpdateWindow(lastHandle);
message.UpdateMessage(i.ToString());
i++;
}
last++;
}
lastHandle = handle;
stillWorking = false;
}
}
All I want to do is draw a box around the window that my mouse is over.
Any ideas, questions, clues, are very much welcome.
Thanks.
|
|
|
|
|
Sounds like a performance issue. Wrapping a Graphics object around an HDC is expensive enough, not to mention all the marshaling involved when you're P/Invoking native APIs.
I would recommend writing an MC++ assembly using native APIs to avoid the marshaling, and don't use a Graphics object: just use GDI APIs (they're really pretty easy for what you're doing) directly. Your C# assembly could reference this assembly and do whatever it needs to. This should greatly improve performance.
I've had to do something similar before when adding functionality to the TreeView class in the BCL and noticed the same thing. If I went slowly (slow mouse movement, etc.) the drawing was fine. It was when I moved at normal or faster speeds that the problem was most definitely obvious.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
"I would recommend writing an MC++ assembly using native APIs to avoid the marshaling"
I'm not quite sure what marshaling is. Is it when I import the API functions? So how would I avoid that?
Thank you for the other tip on dumping the use of Graphics. I'll work on that now and get back with results. Will probably test the code for speed too. So its certain that the problem is performance. I do that using Environment.TickCount. I dont know if thats the best way, but it gives me an idea of how fast things are done during runtime.
|
|
|
|
|
Marshaling describes when memory is transfered from one context to another where the representation may not be the same (.NET marshals objects across AppDomains and ContextBoundaries, and COM (or the host) marshals objects with any external call including to and from .NET). This can be a time consuming process.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Hmmm. I just put
int tick = Environment.TickCount;
on top of the handler and
tick = Environment.TickCount-tick;
MessageBox.Show(tick.ToString());
on the bottom. I run the code, most messageboxes show 0, some show 16 milliseconds to run the whole function.
You still think it might be a performance problem?
I'm not sure, I'm still gonna try only using API calls.
|
|
|
|
|
Is there a program that would allow me to view the messages sent to a particular process. I really feel that the window never gets the message to repaint unless its sent a couple of dozen times. I'm using Bordlands C# Builder if thats relavant, I dont have spy++ or the C# equivalent. (if I'm even correct at assuming that spy++ does what I need)
I looked at the API calls that would draw the rectangle and it looks like only GDI+ can do DrawRectangle. And that function is part of Graphics class. Which looks like the exact equivalent of Graphics.DrawRectangle(). Even in terms of arguments. The tick count to perform DrawRectangle on the graphics object is 0 ms.
Thank you for taking the time to help out.
|
|
|
|
|