|
I am trying to write a method which will get triggered whenever there is a display settings change like resolution change, dual monitor connected and enabled etc. For this I am relying on SystemEvents.DisplaySettingsChanged event.
In the event handler, I am doing the following to detect the active display devices (got this in google search).
[StructLayout(LayoutKind.Sequential)]
public struct DISPLAY_DEVICE
{
public int cb;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string DeviceName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
public string DeviceString;
public int StateFlags;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
public string DeviceID;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
public string DeviceKey;
public DISPLAY_DEVICE(int flags)
{
cb = 0;
StateFlags = flags;
DeviceName = new string((char)32, 32);
DeviceString = new string((char)32, 128);
DeviceID = new string((char)32, 128);
DeviceKey = new string((char)32, 128);
cb = Marshal.SizeOf(this);
}
}
[DllImport("user32.dll")]
public static extern bool EnumDisplayDevices(
string lpDevice, int iDevNum,
ref DISPLAY_DEVICE lpDisplayDevice, int dwFlags);
const int DISPLAY_DEVICE_ACTIVE = 0x01;
const int DISPLAY_DEVICE_PRIMARY_DEVICE = 0x04;
foreach (Screen screen in Screen.AllScreens)
{
LogMsg("Display Device:" + screen.DeviceName + " " + "BPP:" + screen.BitsPerPixel.ToString() + " " + "Width:" + screen.Bounds.Width.ToString() + " " + "Height:" + screen.Bounds.Height.ToString());
DISPLAY_DEVICE monitor = new DISPLAY_DEVICE(0);
monitor.cb = System.Runtime.InteropServices.Marshal.SizeOf(monitor);
LogMsg("Cb:" + monitor.cb.ToString());
EnumDisplayDevices(screen.DeviceName, 0, ref monitor, 0);
LogMsg("State flags:" + monitor.StateFlags.ToString());
if ((monitor.StateFlags & DISPLAY_DEVICE_ACTIVE) == 0x01)
{
LogMsg("Display Device is active");
}
if ((monitor.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) == 0x04)
{
LogMsg("Display Device is primary one");
}
}
What I observed is, the StateFlags is always zero. Then how to check for the active display device?
Is there any other way to detect all the active physical display devices? Any idea whats wrong in the above method?
Also, in the event handler, how to know what caused this event? What I mean is, whether the resolution caused this event or changing to dual monitor caused this event?
Any help or pointer is appreciated.
|
|
|
|
|
This[^] will signal some of the changes you're interested in. When a second monitor is enabled/disabled showing the same image as the primary monitor, I don't expect it to fire though.
|
|
|
|
|
In this line:
EnumDisplayDevices(screen.DeviceName, 0, ref monitor, 0);
You are always passing 0 to iDevNum parameter, so you are always getting the same data. See remarks here[^]. Anyhow, I don't know why you need to use the EnumDisplayDevices function. If you want your primary screen you have it in System.Windows.Forms.Screen.PrimaryScreen, and if you want all the active screens you have them in System.Windows.Forms.Screen.AllScreens. To know what is the reason of the event you can get the configuration at the beginning and compare with it when the event is raised.
|
|
|
|
|
I'm working on one of my first client/server applications. Now my idea is the clients will checkin to the server every 30-60 seconds. When the agent first contacts the server, the server will query the database for "pending actions" (that are placed in there by a control center application), and return those to the client.
So:
Client connects to server (every 60 seconds or so)
Server queries database for actions
Server returns action
Client performs action
Client returns data to server
Server stores updated data in database
Now what I'm doing is passing a serialized object:
[Serializable]
public class Operations
{
[Flags]
public enum Tasks
{
NULL = 0,
CHECKIN = 1,
UPDATE_SERVICES = 2,
UPDATE_PROCESSES = 3,
UPDATE_SOFTWARE = 4,
UPDATE_PRINTERS = 5,
UPDATE_DEVICES = 6,
UPDATE_DRIVES = 7,
UPDATE_SYSTEMBOARD = 8,
UPDATE_COMPUTERINFO = 9,
GET_SERVICES = 10,
GET_PROCESSES = 11,
GET_SOFTWARE = 12,
GET_PRINTERS = 13,
GET_DEVICES = 14,
GET_DRIVES = 15,
GET_SYSTEMBOARD = 16,
GET_COMPUTERINFO = 17,
GET_ALL_DATA = 18,
REGISTER_AGENT = 19
}
public int AgentId { get; set; }
public int AgentLocation { get; set; }
public string Netbios { get; set; }
public Tasks Task { get; set; }
public ComputerInfo ComputerInfo { get; set; }
public SystemBoard SystemBoard { get; set; }
public Processes[] Processes { get; set; }
public IPAddress[] IpAddresses { get; set; }
public Services[] Services { get; set; }
public DiskDrive[] DiskDrives { get; set; }
}
So the client has access to this info as well. So what it does it populate that information. (If the client sets the TASK to UPDATE_SERVICES the client only populates the Services[] array.. not all of the information is populated each time fyi)
Now before I sent or receive I Serialize and Deserialize each side:
IFormatter formatter = new BinaryFormatter();
Operations[] ops (Operations[])formatter.Deserialize(state.ms);
BTW this works fine.. just wondering if its the CORRECT or a GOOD way of doing it.
|
|
|
|
|
If you use Flags attribute for the enum, then the values are absolutely wrong. See this[^]. I think you should remove the Flags attribute on your enum.
Regarding to your question, well, you have not given us much information but, at a firt glance, I don't like the architecture you describe. It is not versatile. Any possible future change will cause a lot of compatibility problems.
|
|
|
|
|
Ill read the Flags attribute.
I have to be able to send the client agents commands to perform which will return data to the server. From there I plan to have a control panel application that will view that information and also be able to send commands to the agents.
Now the agents could be on different networks. Which means that the server cannot create a direct connection to the agents due to them possibly being behind a firewall. So the agent of course has to be the one that first connects to the server.
I guess what I'm asking is if you were creating something like this how would you lay it out? I created the Operations class because it can hold the information, but it doesn't mean that ALL the information will be populated.
Sorry if I'm not explaining it very well.. lets me try it this way:
Client Agent connects to server
Server Accepts connection and queries database for pending actions:
Socket old = iar.AsyncState as Socket;
Socket client = old.EndAccept(iar);
Operations[] ops = AgentActions.GetPendingOperations(1);
MemoryStream ms = new MemoryStream();
IFormatter formatter = new BinaryFormatter();
formatter.Serialize(ms, ops);
client.BeginSend(ms.ToArray(), 0, (int)ms.Length, 0, new AsyncCallBack(SendCallback), client);
The pending actions table is just the AgentId and the TaskId (which matches the ENUM).
So at this point the client is receiving information from the server about what actions it should perform:
int bytesRead = client.EndReceive(iar);
if (bytesRead > 0)
{
state.ms.Write(state.buffer, 0, bytesRead);
if (bytesRead == StateObject.BufferSize)
client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReceiveCallback), state);
else
{
state.ms.Seek(0, SeekOrigin.Begin);
IFormatter formatter = new BinaryFormatter();
Operations[] ops = (Operations[])formatter.Deserialize(state.ms);
}
}
Here is my state object:
public class StateObject
{
public Socket workSocket = null;
public const int BufferSize = 1024;
public byte[] buffer = new byte[BufferSize];
public MemoryStream ms = new MemoryStream();
}
I hope that helps in explaining what I'm trying to do. Like I said it works. I can send the Operations array back and forth and insert it in the DB and what not but I'm just wondering if there is another way I should be doing this.
|
|
|
|
|
Hmmm, I don't know... I don't like it. I still think this architecture is too rigid. Your current implementation is too concrete and the communication layer depends too much on the concrete types you are using. If you had to add some extra features to the Operations in the future you would be in trouble. Your communication layer should be much more abstract. See SOLID principles[^] for object oriented design.
However, if you anticipate that the functional requirements for this application will not change nor grow in the future, then what you have done might be enough.
|
|
|
|
|
I'll read what you sent and see if I can figure out a good way to change it differently. I mean I have to pass a custom object between the agent and server. That Operations object is a custom object. So if I ever did updates inthe future I would just add it, and then the server would be updated and agents as well.
|
|
|
|
|
Yep, I know what you mean. My very first client-server solution architecture was really very similar to yours. It was simple and worked very well, but as requirements grew up the maintenance became a pain in the neck. Every change required a new server version and a new client version, and every new piece of software had to be deployed everywhere within the less period of time, becouse there were usually compatibility issues between the new versions and the old ones, and many other headaches.
My last client-server architecture is absolutely different. The communication layer is stable, I mean, no matter what information comes and goes, this layer can handle it without any change. Both, client and server layers can be easily extended: there is no need to recompile them. Still more, there is no need to stop them. Each one of these two sides is a simple application which only has to load or unload plugins. I don't even have to change the database structure. When there is a problem with a plugin I only have to change, recompile and replace its library. Sure, the associated module will not be available during the change, but the rest of the application will keep working.
|
|
|
|
|
I think I see what your saying but I just can't wrap my head around what I should do. I mean I have to pass a certain data structure because this information will be getting stored in a database. So the columns have to match up some way or another.
Unless I'm making the clients pass the SQL commands and parameters along with the values to the server, it only seems like if an update was to happen it would have to update the server and clients.
|
|
|
|
|
You didn't happen to write an article on this did you? I would like to see similiar code so I can better understand what I need to do. As I sit right now I am unable to come up with a better solution than passing my custom object (differnet compiled dll) back and forth. The client sends the custom object, the server reads it, and depending on which task was set it calls a different method to insert the data (or update) into a SQL database.
|
|
|
|
|
No, sorry. Actually I thought about that possibility, but after considering what should be included I noticed it should be too large: it should cover several OOD principles and patterns and a huge application of multitier alchitecture, too large as I said and unfortunately I do not have so much time. Anyway, the success of these designs relies on a good abstraction, and I did write an article which intensely uses abstraction and, though it has nothing to do with client-server communication, maybe it can give you some clues in order to get a better abstraction for your application. Here is the link[^].
In the case you describe, for example, the client should send an abstraction of the custom object, the server should read this abstraction and call always the same method on this abstract object to insert the data. How to send an abstraction of a custom object? Well, design an interface and wrap your custom object within a class which implements this interface. This way your server only needs to look at the interface and invoke its methods, so it can work for any custom object (present or future) if it follows the abstraction rules. It is really hard to explain this here: there are a lot of things involved but, as I said before, the key is a good abstraction.
|
|
|
|
|
Hi,
I am programming a softphone in C#. Now i want to monitor the phone(extension) state. The phone is a local phone. I think the best method is with a subscription to an extension and receive the state by notifications from this extension. An example: when a phone is busy, i get a notify and a light will be orange. When the phone is available the light will be green. How can i do this?
Thanks..
|
|
|
|
|
Hello,
I have some executable code which sends a message to some process, this message opens a "save as" dialog. (regular window's dialog)
The question is how can also pass arguments (a path to save in) to the launched dialog ?
Do i need to use my application API, or there is some other way to do it by using windows messages
Thanks
|
|
|
|
|
There is something confusing about your question but I will provide what I think is an answer.
Are you using a SaveFileDialog ? As this has a property called InitialDirectory which you can set to be the path to save the file in...
SaveFileDialog sfd = new SaveFileDialog();
sfd.InitialDirectory = @"C:\my_folders\folder_to_save_in\";
if(sfd.ShowDialog() == DialogResult.OK){
}
I don't think you can force the user to save in that folder only but there are a couple of options if you need that functionality?
Life goes very fast. Tomorrow, today is already yesterday.
|
|
|
|
|
Depending on the message you are sending you could add the path as either the WPARAM or LPARAM of the message.
Just say 'NO' to evaluated arguments for diadic functions! Ash
|
|
|
|
|
that's how it works :
IntPtr QTPHandle = FindWindow(null, qtp[0].MainWindowTitle);
SetForegroundWindow(QTPHandle);
SendKeys.SendWait("{F4}");
|
|
|
|
|
OK, obviously my suggestion will not work as you are sening a keystroke to a window, rather than invoking a function within the application. Assuming this is going to an external application then I do not think you can do what you are asking.
Just say 'NO' to evaluated arguments for diadic functions! Ash
|
|
|
|
|
but when i open a "save as" dialog isn't it possible to "catch it" ?
|
|
|
|
|
igalep132 wrote: but when i open a "save as" dialog isn't it possible to "catch it" ?
I suppose it is but I don't know how you would add your path into the dialog without knowing which message to send it. I'm also still unsure whether you are sending the "F4" key to an external application, or merely to a Window of your own application. Whichever you are doing will affect what you can or cannot do.
Just say 'NO' to evaluated arguments for diadic functions! Ash
|
|
|
|
|
the "F4" is for "my" app, and my app launch standard windows "Save as" dialog
|
|
|
|
|
igalep132 wrote: the "F4" is for "my" app, and my app launch standard windows "Save as" dialog
So you just need some pice of communication that will allow your path to be sent to your app. Take a look at Luc's answer (and link) below, it will probably help with what you need to do.
Just say 'NO' to evaluated arguments for diadic functions! Ash
|
|
|
|
|
more precisely, you could pass a pointer to a string through LPARAM, however that pointer must point to some valid memory in the target process; this requires some P/Invoking of kernel functions such as AllocateVirtual, ReadProcessMemory, WriteProcessMemory. I once developed a little LP_Process class that encapsulates all this, see e.g. here: LP#TrayIconBuster[^]
|
|
|
|
|
i have done the encryption for black and white images but the processing time is high as the size increases.i want a help to lower the process time. i like to know how to modify for color images.i have done the encryption using the base paper"A hash based image encryption algorithm" from a journal published by Elsevier
|
|
|
|
|
Why would a colour image be any different from black and white? (in terms of how you process it)
Also, depending on format of image color and black and white may be the same data size
More info on you code please!!!
Life goes very fast. Tomorrow, today is already yesterday.
|
|
|
|
|