|
UpdateWindow sends the WM_PAINT message to the immediate window without posting to the message queue. Just make sure you're sending client coordinates and not screen coordinates.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Finally fixed.
I dont know what the problem was, deffinitely related to the API functions mentioned previously. However, drawing on the desktop DC instead of the individual window DC and then updating the desktop, solved the problem. One other way to solve my problem I guess could be using PostMessage to post the WM_PAINT message to the window manualy.
Thank you very much for you help Heath. You gave me a lot of usefull information that lead me to the solution.
And here is the working code, in case someone could find it usefull. I will be working on another approach to what this handler does, something that wont cause so much flickering on the screen and as soon as I have it, I will post the code in this thread or if someone could suggest the best place to put something like this just for refference.
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(IntPtr.Zero);
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,2),dcRect.x1+regionRect.x1,dcRect.y1+regionRect.y1,width,height);
first=1;
}
else if(!(lastHandle.Equals(handle)))
{
//IntPtr lastDC = USER32.GetWindowDC(lastHandle);
//testDraw = Graphics.FromHdc(lastDC);
if(first!=0)
{
USER32.Rect dcRect= new USER32.Rect();
USER32.GetWindowRect(IntPtr.Zero,ref dcRect);
USER32.InvalidateRect(IntPtr.Zero, ref dcRect,false);
USER32.UpdateWindow(IntPtr.Zero);
}
}
lastHandle = handle;
stillWorking = false;
}
}
|
|
|
|
|
Well this was relatively fast and easy.
Here is a MUCH better way to draw a box around the window that the mouse is moving over.
First create a new form. Magenta background. TransparencyKey magenta. TopMost true. ShowInTaskBar false. Normal window state. Any size and position. FormBorderStyle none.
Create a new onpaint event handler.
//this basically draws a nice 3d looking border INSIDE the form
private void ControlSelectorForm_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
{
Graphics myGraphics = e.Graphics;
Pen myBlackPen = new Pen(Color.Black,1);
myBlackPen.Alignment = PenAlignment.Inset;
Pen myRedPen = new Pen(Color.Red,2);
myRedPen.Alignment = PenAlignment.Inset;
myGraphics.DrawRectangle(myBlackPen,0,0,this.Width-1,this.Height-1);
myGraphics.DrawRectangle(myRedPen,1,1,this.Width-2,this.Height-2);
myGraphics.DrawRectangle(myBlackPen,3,3,this.Width-7,this.Height-7);
}
Go to your main window mouse handler (which is linked to a system hook in my case, http://www.codeproject.com/csharp/globalhook.asp)
You should make it something like this and it does the job.
//selector is a global declaration of ControlSelectorForm and it is set to new ControlSelectorForm() on mouse click
//that starts the system wide mouse hook
private void MovingMonitor(object sender, MouseEventArgs e)
{
//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);
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.",
"Warning!",MessageBoxButtons.OK,MessageBoxIcon.Warning);
width = dcRect.x2 - dcRect.x1;
height = dcRect.y2 - dcRect.y1;
break;
}
selector.Width = width;
selector.Height = height;
selector.Left = dcRect.x1+regionRect.x1;
selector.Top = dcRect.y1+regionRect.y1;
selector.Show();
}
|
|
|
|
|
Hi,
I'd like to use "contexMenu" in my "TreeView" for
specific "Node".
eg. I have TreeViev likes below ...
Node_1
Node_1.1
Node_1.2
Node_1.3
Node_2
Node_2.1
Node_2.2
Node_2.3
...and I want to use "contexMenu_1" for "Node_1.1"
and "Node_2.1" and
"contexMenu_2" for "Node_1.2" and "Node_2.2" etc.
It looks like "Microsoft Menagement Console"
I can use
treeView1.ContextMenu = this.contextMenu1;"
but I cannot use
treeView1.Nodes[number].ContextMenu =
this.contextMenu1;
I don't know how can I use "contexMenu in this case.
Thanks for help,
Kamil
|
|
|
|
|
Add a MouseUp event handler to the TreeView. In the event handler, it would look something like
private void treeView1_MouseUp(object sender, MouseEventArgs e)
{
if(e.Button == MouseButtons.Right)
{
TreeNode clickedNode = tv.GetNodeAt(MousePosition);
if(tv == node_1.1) treeView1.ContextMenu = contextMenu1;
else if (tv == node_1.2) ... and so on
}
}
#include "witty_sig.h"
|
|
|
|
|
Judah Himango wrote:
private void treeView1_MouseUp(object sender, MouseEventArgs e){
if(e.Button == MouseButtons.Right)
{
TreeNode clickedNode = tv.GetNodeAt(MousePosition);
if(tv == node_1.1) treeView1.ContextMenu = contextMenu1;
else if (tv == node_1.2) ... and so on
}
}
Thanks for advice but it not solve my problem, because it calls "NullException....".
...by the way it should be written in this way
private void treeView1_MouseUp(object sender, MouseEventArgs e){
if(e.Button == MouseButtons.Right) {
TreeNode clickedNode = tv.GetNodeAt(MousePosition);
if(clickedNode == node_1.1) treeView1.ContextMenu = contextMenu1;
else if (clickedNode == node_1.2) ... and so on }
}
"NullException..." isn't call in this case.
private void treeView1_MouseUp(object sender, MouseEventArgs e){
if(e.Button == MouseButtons.Right) {
TreeNode clickedNode = tv.GetNodeAt(e.X, e.Y);
if(clickedNode == node_1.1) treeView1.ContextMenu = contextMenu1;
else if (clickedNode == node_1.2) ... and so on }
}
Thanks for your help.
Kamil
|
|
|
|
|
hello,
maybe this can help
private void treeView1_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e)
{
if(e.Button == MouseButtons.Right)
{
System.EventArgs a = new EventArgs();
Point ClickPoint = new Point(e.X,e.Y);
TreeNode ClickNode = treeView1.GetNodeAt(ClickPoint);
ruletree.SelectedNode=ClickNode;
if(ClickNode == null) return;
Point ScreenPoint = ruletree.PointToScreen(ClickPoint);
Point FormPoint = this.PointToClient(ScreenPoint);
ContextMenu treeRCMenu = new ContextMenu();
MenuItem mnuRenamePNode = new MenuItem("Rename Node");
if(clickedNode == node_1.1)
{
treeView1.ContextMenu = contextMenu1;
}
else if (clickedNode == node_1.2) ... and so on }
}
be sure to have named you context menu items and initialized them, to use them , you might have to add the event hadler for them.
like:
MenuItem mnuRenamePNode = new MenuItem("Rename Parent Node");
MenuItem mnuRenameCNode = new MenuItem("Rename Child Node");
mnuRenamePNode.Click +=new EventHandler(mnuRenamePNode_Click);
mnuRenameCNode.Click +=new EventHandler(mnuRenameCNode_Click);
|
|
|
|
|
Hey,
I am trying to get a string returned from my managed code to my unmanaged code. Basically what I have so far is an interface as follows:
<br />
[ComVisible(true)]<br />
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]<br />
[Guid("")]<br />
<br />
public interface IGet<br />
{<br />
void GetString([MarshalAs(UnmanagedType.LPWStr)] out string Value);<br />
}<br />
<br />
public class PropertyGet : IGet<br />
{<br />
public PropertyGet(Item item)<br />
{<br />
m_item = item;<br />
}<br />
<br />
public void GetString(out string Value)<br />
{<br />
Property prop = m_item.GetProperty();<br />
<br />
Value = prop.ToString();<br />
}<br />
}<br />
In the managed code
<br />
HRESULT CFileProperties(BSTR fileName, IGet pIGet)<br />
{<br />
WCHAR wszWideBuffer[1024];<br />
wszWideBuffer[0] = NULL_CHARACTER;<br />
pIGet->GetString(wszWideBuffer);<br />
}<br />
So in the managed code right now, the wszWideBuffer is filled with some wierd characters. So something is not marshalling correctly and with my limited experience I am not sure where to look for the problem. Most articles seem to handle passing strings the other way (i.e. getting a string back from the unmanaged which works in my property setting code.)
Any help would be appreciated.
Brian
If you start a fire for a man, he will be warm for a day. If you start that same man on fire, he will be warm for the rest of his life.
|
|
|
|
|
You need to pass the address of wszWideBuffer . String is already a reference type (a managed pointer, if you will), so out string is a pointer to a pointer, in essense. So, you should pass &wszWideBuffer .
On a side note, you might consider marshaling your string as UnmanagedType.BStr (which is a length-prefixed wide character array). This is more common in COM and necessary for OLE automation (if you plan on support automation clients like VB6 and older).
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Thanks for the response.
I did try that and it caused me some issues with building the unmanaged code. However I was able to change the string to a stringbuilder which is listed as a both an in and out in the built type library. This was suggested in the big purple book that I borrowed from a friend.
Thanks,
Brian
If you start a fire for a man, he will be warm for a day. If you start that same man on fire, he will be warm for the rest of his life.
|
|
|
|
|
I would like to know if I can run microsoft.office.interop 11.0 (office 2003) on the .NET 1.0 framework?? And if I have both office.interop 10.0 and 11.0 assemblies on my pc, how do I force Visual Studio to use Office.Interop.Excel 10.0??
Kind regards,
Dries
|
|
|
|
|
The Office 11 PIAs (Primary Interop Assemblies) use .NET 1.1 (1.0.5000.0 for the .NET BCL assemblies), but you can redirect assembly versions to .NET 1.0 (1.0.3300.228 for .NET 1.0 BCL assemblies with SP2). Read Redirecting Assembly Versions[^] in the .NET Framework SDK for more information.
However, you should keep in mind that if you're not using any new features of Office 11 (2003), then you can use older interop assemblies. OLE automation - when done right like it is in Office - maintain backward compatibility (rarely have there been breaking changes in the typelibs for Office). But using a new interop assembly (which is created from a typelib) may not support older versions since interface IDs may be different.
If you want to support both Office XP and 2003, use the Office XP interop assemblies. They'll still work with Office 2003. If you want to support Office 2000 and newer, create interop assemblies for Office 2000. This should work all the way back to Office 97, but I wouldn't go beyond 2000, IMO.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
I've implemented the IDropTargetHelper and IDragSourceHelper COM interfaces to augment my drag drop support. So far I can create the IDropTargetHelper interface and call the respective methods will absolutely no problem. I should be able to use the exact same logic to create and use an IDragSourceHelper objedt. For some reason I get the following error when trying to create the object:
"COM object with CLSID {DE5BF786-477A-11D2-839D-00C04FD918D0} is either not valid or not registered."
I've triple checked and the GUID is correct for the IDragSourceHelper interface. Does anyone know what can be done here? Does somet DLL need to be registered? I'm out of ideas.
Thanks
|
|
|
|
|
It's the IID (interface GUID) that's the problem, but the COM object GUID (that's what a CLSID is - a GUID for a class). You must have defined an interop class for the shell object that implements IDragSourceHelper .
See, you don't actually create an interface; an interface is abstract and can't be instantiated. What happens behind the scenes (in the CLR) is that the COM object is created and AddRef'd. The CLR QI's (QueryInterface) for the interface when you perform a cast and returns the interface you want (to which you're casting).
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Perhaps I wasn't clear enough in my question...
I already have all the interop classes created. (That's was my point in saying I have everything working for the IDropTargetHelper interface). I wasn't suggesting I was trying to create an interface - I was sparing a paragraph spelling out what my already working code does. My question was why I can get the IDropTargetHelper working but not the IDragSourceHelper using the same overall logic.
Now - according to shlguid.h the IID for the drop helper (IID_IDropTargetHelper) is 4657278B-411B-11d2-839A-00C04FD918D0. That works - no problem there at all.
It would stand to reason, then, that the guid for IID_IDragSourceHelper would work for using the IDragSourceHelper interface. IID_IDragSourceHelper is DE5BF786-477A-11d2-839D-00C04FD918D0. That's the part that doesn't work - when I create the object derived from the IDragSourceHelper interface I get the message specified in my first post.
Oddly, the value 4657278B-411B-11d2-839A-00C04FD918D0 is in my registry in several places, while DE5BF786-477A-11d2-839D-00C04FD918D0 is not in my registry.
|
|
|
|
|
Look man, I don't know you. I don't know most of the people that show up in this forum looking for help. The only person I truly know here is Nick and I'm familiar with a few others that frequent this forum like Dave and Christian.
When people come to this forum, I assume nothing. I don't know if you know what you're doing. Since you're peering into header files and based on other information, it appears you do know what you're doing; but how could've I known that? As I said, I don't know you. So please don't get testy.
Sorry, it's just that I've been getting a lot of this crap lately because forums present faceless people sitting on a keyboard potentially on the other side of the world.
As for your questions and comments...
IIDs don't have to be registered, so the fact that IID_IDragSourceHelper isn't found in your registry isn't not surprising. Of course the CLSID must be registered, which I'm sure you know.
The documentation for both the IDropTargetHelper and IDragSourceHelper interfaces state that the COM object with CLSID_DragDropHelper implements both. When I import shell32.dll, however, this coclass isn't imported, so I'm curious where you got it (or did you declare the class yourself, which is entirely possible).
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
I three together the follow. The ComImportAttribute changes the metadata such that an instance is marked as imported and created from the attributed GUID. By casting, I am effectively QI'ing for the two interfaces.
In both cases, "False" is printed to the console, showing that the object does implement both interfaces. Sorry I don't have time to throw together a better sample (and keep in mind that when using interfaces not every method has to be defined (so long as they're in the correct VTBL order):
using System;
using System.Runtime.InteropServices;
[
GuidAttribute("4657278A-411B-11d2-839A-00C04FD918D0"),
ClassInterface(ClassInterfaceType.None),
ComImport
]
public class DragDropHelper : IDropTargetHelper, IDragSourceHelper
{
}
[
GuidAttribute("4657278B-411B-11d2-839A-00C04FD918D0"),
InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
ComImport
]
public interface IDropTargetHelper
{
}
[
GuidAttribute("DE5BF786-477A-11d2-839D-00C04FD918D0"),
InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
ComImport
]
public interface IDragSourceHelper
{
}
class Test
{
static void Main()
{
DragDropHelper helper = new DragDropHelper();
IDropTargetHelper dropHelper = (IDropTargetHelper)helper;
IDragSourceHelper dragHelper = (IDragSourceHelper)helper;
Console.WriteLine(dropHelper == null);
Console.WriteLine(dragHelper == null);
}
}
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Hi, guys, I have a form(window1) and I want click a button and then display another form(window2). If I use window2.ShowDialog(), window2 is displayed correctly. But I would like to use window2.Show(), the label control on the form can n't display correctly. Why/
Who can help me?
Thank you very much.
vigorous
|
|
|
|
|
If you include code, we can better help you. Does you you button handler look like this?
private void button_Click(object sender, EventArgs e)
{
OtherWindow other = new OtherWindow();
other.Show();
}
- Nick Parker My Blog | My Articles
|
|
|
|
|
Yes ,you are right. The code is very similar.
Do you know the reason of display incorrectly?
Thank you
vigorous
|
|
|
|
|
What exactly do you mean it "display[s] incorrectly?" Please be specific or we can't help you.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
I am importing data from file into arraylists. Then I use the arraylists to fill a DataTable that I use as a DataSource for a DataGrid. But when I refill the Grid with new data from files, selection by pressing rowheader gets slower and slower. I get a delay before the entire row is highlighted. If I select a cell first, then the rowheader for the row containing that cell, the delay is not there. It only happens after refilling the table/grid a couple of times. It alså happens if I add columns to the table at run time (after adding about 5 columns it gets a noticable delay). What is up with that?
-Atle
|
|
|
|
|
I want to check a string entered in a TextBox & check wether it has valid C# stements.. or a part of C# statements (maybe MessageBox es )
How can I do that?
_____________________________________________________
Yea! I could be wrong...
|
|
|
|
|
yes.....it is:
if(string == "something"){ }
|
|
|
|
|
SJ_Phoenix wrote:
if(string == "something"){ }
This is not the best method for checking a string. Instead, do something below:
string s = "Nick";
if(string.Compare(s, "Nick") == 0)
{
}
- Nick Parker My Blog | My Articles
|
|
|
|
|