|
Hello all;
I have some classes based on an interface that I need to raise events in an implementing form. However I do not want to create add an event handler definition for all the instances as in Form1_NotWhatIWant in the source sample below.
I would like to define an event handler ONCE, linked to the interface and then, any instantiated class that implements the interface will have the event handler ready.
If not an interface, can it be done through an Abstract baseclass.
I hope the query and code sample are clear enough. A clear answer is appreciated as some I found online did not explain it well. Regardsless, all help is accepted and appreciated.
Thanks
B.
public delegate void CountReachedDelegate(IBase iBase, string Message);
public interface IBase
{
Int32 Trigger {get;}
String Name { get; }
void Count(int Limit);
event CountReachedDelegate CountReached;
}
public class SubIntA: IBase
{
#region IBase Members
private int _T = 20;
public int Trigger
{
get { return _T; }
}
string _N = "A";
public string Name
{
get { return _N; }
}
public void Count(int Limit)
{
for (int x = 0; x < Limit; x++)
if (x % _T == 0)
if (CountReached != null)
CountReached(this, _N + "=" + x.ToString());
}
public event CountReachedDelegate CountReached;
#endregion
}
public partial class Form1_NotWhatIWant : Form
{
IBase A = new SubIntA();
IBase B = new SubIntB();
public Form1_NotWhatIWant ()
{
InitializeComponent();
A.CountReached += new CountReachedDelegate(CountReached);
B.CountReached += new CountReachedDelegate(CountReached);
}
void CountReached(IBase iBase, string Message)
{
listBox1.Items.Insert(0, iBase.GetType().ToString() + ": " + Message);
}
private void button1_Click(object sender, EventArgs e)
{
A.Count(100);
}
private void button2_Click(object sender, EventArgs e)
{
B.Count(150);
}
}
public partial class Form1_WhatIWouldLike : Form
{
IBase A = new SubIntA();
IBase B = new SubIntB();
public Form1_WhatIWouldLike()
{
InitializeComponent();
IBase.CountReached += new CountReachedDelegate(CountReached);
}
void CountReached(IBase iBase, string Message)
{
listBox1.Items.Insert(0, iBase.GetType().ToString() + ": " + Message);
}
private void button1_Click(object sender, EventArgs e)
{
A.Count(100);
}
private void button2_Click(object sender, EventArgs e)
{
B.Count(150);
}
}
|
|
|
|
|
I tend to write an abstract class to go with the interface.
|
|
|
|
|
So what you're wanting is to expose the event at the type level, not the instance level.
Since interfaces do not allow static members, you'll have to create an abstract base class:
public delegate void CountReachedDelegate(CountableBase countableBase, string message);
public abstract class CountableBase
{
public static event CountReachedDelegate CountReached;
public static void OnCountReached(CountableBase item, string message)
{
CountReachedDelegate del = CountReached;
if (del != null)
del(item, message);
}
public abstract void Count(int limit);
}
public class SubIntA : CountableBase
{
private int _T = 20;
public int Trigger
{ get { return _T; } }
string _N = "A";
public string Name
{ get { return _N; } }
public override void Count(int limit)
{
for (int x = 0; x < limit; x++)
if (x % _T == 0)
OnCountReached(this, _N + "=" + x);
}
}
public class SubIntB : SubIntA { }
Note that I've implemented SubIntA and SubIntB one in terms of the other. Of course, your app will be different in that regard. Depending on the degree of similarity between these classes, I'd recommend moving any count-related behavior, especially if it relates to the threshold, into the abstract base class. The aim here is to keep all related behavior in the same class (and, ideally, all behavior in a class is related to all other behavior in the class and all unrelated behavior is in another class).
BTW: your threshold check condition (x % _T == 0 ) will fire on x == 0 and on the threshold. Probably not what you want.
|
|
|
|
|
Thanks for this. I can adapt it very easily in my project.
|
|
|
|
|
I have an application that spits out binary masks to file. These files are simply a long string of bits, each set to 1 or 0. There is no metadata or header; you need to know the dimensions of the mask before processing it. I would like to convert these files into bitmaps for each of visualization.
I have code that works, but it's extremely inefficient (40 seconds for a 1025x1025 pixel image). This mechanism runs through the bits one at a time, tests each one and sets the bits of a bitmap individually to black or white based on the test result. Can anyone suggest a more efficient method?
public static void FileToImage(string path)
{
byte[] data;
using (FileStream fs = File.OpenRead(path))
{
data = new byte[fs.Length];
ReadWholeArray(fs, data);
}
int i = 0;
int numPixels = 1025;
Bitmap bmp = new Bitmap(numPixels, numPixels);
for (int y = 0; y < numPixels; y++)
{
for (int x = 0; x < numPixels; x++)
{
if (data[i++] == 0)
{
bmp.SetPixel(x, y, Color.Black);
}
else
{
bmp.SetPixel(x, y, Color.White);
}
}
}
bmp.Save(path + ".bmp");
}
private static void ReadWholeArray(Stream stream, byte[] data)
{
int offset = 0;
int remaining = data.Length;
while (remaining > 0)
{
int read = stream.Read(data, offset, remaining);
if (read <= 0)
throw new EndOfStreamException
(String.Format("End of stream reached with {0} bytes left to read", remaining));
remaining -= read;
offset += read;
}
}
|
|
|
|
|
How about creating a bitmap with a white background, and only add the black spots?
..if you only need to add black spots, and an entire row in the matrix consists of "black spots", would it be feasible to draw an entire line, as opposed to dots?
OTOH, think you might also be able to convert it to a memorystream, and try to instantiate a bitmap from that stream.
Time for some sleep, curious what other solutions appear on this question
I are Troll
|
|
|
|
|
Never use GetPixel or SetPixel if it has to be fast. Use LockBits and unsafe code instead. It's several orders of magnitude faster for reasonable bitmap sizes (anything larger than just a couple of pixels).
|
|
|
|
|
If your pixel data is using one of the standard formats, you can use this Bitmap constructor[^] to directly create the bitmap in a jiffy, without worrying about the header. Warning: do read the Remarks section on the MSDN page!
As there is a 1-bit-per-pixel format (PixelFormat.Format1bppIndexed) this could do the trick, but I cannot confirm from experience as I've never used it so far.
|
|
|
|
|
All good suggestion. Thank you guys!
I was hoping to avoid LockBits, since this technique presupposes that the developer understands the in-memory representation of each PixelFormat. I didn't have that knowledge, and didn't want to learn it unless absolutely necessary. But it turns out that Bitmap.SetPixel() performs a lock and unlock every time a bit is set, which is hugely inefficient. So it appeared I had no choice...
So I bit the bullet, hopped on Google and found everything I needed to know at Bob Powell's site: http://www.bobpowell.net/lockingbits.htm[^]. Here is the resulting code:
public static void FileToImage(string path, int imageHeight, int imageWidth)
{
byte[] data;
using (FileStream fs = File.OpenRead(path))
{
data = new byte[fs.Length];
ReadWholeArray(fs, data);
}
Bitmap bmp = new Bitmap(imageWidth, imageHeight, PixelFormat.Format1bppIndexed);
Rectangle bounds = new Rectangle(Point.Empty, bmp.Size);
BitmapData bmpData = bmp.LockBits(bounds, ImageLockMode.WriteOnly, bmp.PixelFormat);
int iBitList = 0;
unsafe
{
Byte* bmpDataPointer = (Byte*)bmpData.Scan0.ToPointer();
for (int y = 0; y < imageHeight; y++)
{
for (int x = 0; x < imageWidth; x++)
{
int iBitmap = y * bmpData.Stride + (x >> 3);
byte mask = (byte)(0x80 >> (x & 0x7));
if (0x0 == data[iBitList])
{
}
else
{
bmpDataPointer[iBitmap] |= mask;
}
iBitList++;
}
}
}
bmp.UnlockBits(bmpData);
bmp.Save(path + ".bmp");
}
When the BitmapData object is constructed, it automatically sets all pixels to 0 (black), so setting just the white pixels is perfectly valid.
That being said, this technique is so fast that it actually make no difference at all. Processing three 1025x1025 pixel images took 93 ms either way. Incidentally, this is over 400 times faster than Bitmap.SetPixel(). Wow!
Just remember - this uses pointers and unsafe code. Select 'Allow unsafe code' in the project properties (Build tab).
|
|
|
|
|
Glad you got it working.
However, as I said earlier, I think most of your code is unnecessary as there is at least one Bitmap constructor that takes raw data as is, provided it conforms to one of the supported pixel formats; chances are good it does.
|
|
|
|
|
I knew there was something I forgot to mention. Thanks for the reminder Luc.
I assumed that the data format does not conform to any bitmap standards for two reasons:
1) I made up the format of the raw data, and it's just a string of bits. No encoding or anything.
2) I tried using the standard Bitmap constructors, and they garbled the data pretty badly.
|
|
|
|
|
for 1-bit-per-pixel data, there is only so much you can choose. IMO chances are great your intuitive choices are what PixelFormat.Format1bppIndexed also does. The biggest uncertainty would be the ordering of the 8 pixels that constitute a byte. there is 50% chance there.
|
|
|
|
|
what the meaning of this code
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
namespace DESERT_Server_v2
{
class Win32Stuff
{
#region Class Variables
public const int SM_CXSCREEN = 0;
public const int SM_CYSCREEN = 1;
public const Int32 CURSOR_SHOWING = 0x00000001;
[StructLayout(LayoutKind.Sequential)]
public struct ICONINFO
{
public bool fIcon;
public Int32 xHotspot;
public Int32 yHotspot;
public IntPtr hbmMask;
public IntPtr hbmColor;
}
[StructLayout(LayoutKind.Sequential)]
public struct POINT
{
public Int32 x;
public Int32 y;
}
[StructLayout(LayoutKind.Sequential)]
public struct CURSORINFO
{
public Int32 cbSize;
public Int32 flags;
public IntPtr hCursor;
public POINT ptScreenPos; }
#endregion
#region Class Functions
[DllImport("user32.dll", EntryPoint = "GetDesktopWindow")]
public static extern IntPtr GetDesktopWindow();
[DllImport("user32.dll", EntryPoint = "GetDC")]
public static extern IntPtr GetDC(IntPtr ptr);
[DllImport("user32.dll", EntryPoint = "GetSystemMetrics")]
public static extern int GetSystemMetrics(int abc);
[DllImport("user32.dll", EntryPoint = "GetWindowDC")]
public static extern IntPtr GetWindowDC(Int32 ptr);
[DllImport("user32.dll", EntryPoint = "ReleaseDC")]
public static extern IntPtr ReleaseDC(IntPtr hWnd, IntPtr hDc);
[DllImport("user32.dll", EntryPoint = "GetCursorInfo")]
public static extern bool GetCursorInfo(out CURSORINFO pci);
[DllImport("user32.dll", EntryPoint = "CopyIcon")]
public static extern IntPtr CopyIcon(IntPtr hIcon);
[DllImport("user32.dll", EntryPoint = "GetIconInfo")]
public static extern bool GetIconInfo(IntPtr hIcon, out ICONINFO piconinfo);
#endregion
}
}
|
|
|
|
|
It's a wrapper class that links to API calls.
"WPF has many lovers. It's a veritable porn star!" - Josh Smith As Braveheart once said, "You can take our freedom but you'll never take our Hobnobs!" - Martin Hughes.
My blog | My articles | MoXAML PowerToys | Onyx
|
|
|
|
|
Hello everyone,
I encountered the following problem :
I want to make a C like interpreter and I've found some good materials but only in C. So I have a (modest but) functional interpreter written in C and I would like to improve it in C#.
I don't know how to make a .dll from that C code and if I could maybe I could invoke it from C#, or I could rewrite the whole program in C# but in .NET I don't have
<#include setjmp.h> which is used in the C interpreter.
So if anyone knows how to make a .dll or something I could invoke from C# or if it is any alternative to
#include <setjmp.h> in .NET please let me know!
Thanks in advance,
Tamash
|
|
|
|
|
You can make a dll in C# by making a Class Library project.
To call the C code from C#, you will need to research P/Invoke. You will need to replicate all the function signatures, structures and constants in the C header file in C#
DaveIf this helped, please vote & accept answer!
Binging is like googling, it just feels dirtier.
Please take your VB.NET out of our nice case sensitive forum.(Pete O'Hanlon)
BTW, in software, hope and pray is not a viable strategy. (Luc Pattyn)
|
|
|
|
|
Hi,
if you really want to go the trouble, study P/Invoke. I have a little article[^] that might help.
However, I wouldn't do such things in C nowadays, C# is much easier. You do not really need setjmp, there are several ways to avoid it, e.g. restructuring your set of methods; what you also could do is use a specialized exception. Partial example:
try {
} catch(SetjmpLikeException exc) {
} catch(Exception exc) {
}
...
throw new SetjmpLikeException();
...
public class SetjmpLikeException : Exception {
}
|
|
|
|
|
I wrote a program for Windows XP that does not function in Windows 7. Is there a way I can build the program in Visual Studio so that it will require Windows XP to install?
|
|
|
|
|
The first thing to do would be understand why it doesn't work on Windows 7, you shouldn't be creating an app that is dependent on an older OS.
You can check for the OS version at startup but the logical thing would to would be prevent it from installing in the first place via the setup.
I know the language. I've read a book. - _Madmatt
|
|
|
|
|
Mark Nischalke wrote: the logical thing would to would be prevent it from installing in the first place via the setup.
I agree. This is what my question pertains to.
|
|
|
|
|
Then it depends on what tool you are using to create the installation package. You can create a custom action to validate the OS level.
I know the language. I've read a book. - _Madmatt
|
|
|
|
|
It is a Visual Studio project, and so far I have been using Video Studio to create the installers. Is this possible to do with Visual Studio?
|
|
|
|
|
Yes. There are plenty of examples for creating custom actions with Visual Studio
I know the language. I've read a book. - _Madmatt
|
|
|
|
|
Fix the program; what problem does it have?
|
|
|
|
|
Come on, when a program depends on some third party components, that's pretty normal. And nothing you can change!
|
|
|
|
|