I have been referring the "CefGlue.Samples.WpfOsr" inside the CEFGlue samples available at https://bitbucket.org/xilium/xilium.cefglue/downloads and trying to integrate the same in a plug-in assembly. No matter what ever I do, the browser control doesn't get renderd in the view when run as a plug-in. However this works fine when run in standalone mode. Can someone advise how to go about?
So I found the root cause why the control was not showing up. Somewhere in the CEFGlue code base was following line, which makes it traverse the visual tree all the way up looking for type “Window” so as to get its parent window handle and render CEFBrowser control's UI.
Window parentWnd = FindParentOfType<Window>(this);
private static T FindParentOfType<T>(DependencyObject obj) where T : DependencyObject
{
DependencyObject parentObj = VisualTreeHelper.GetParent(obj);
if (parentObj == null)
return null;
// Try to type cast the parent to the desired type.
// If the cast succeeds, we've found the desired parent.
T parent = parentObj as T;
if (parent != null)
return parent;
// If we get here, the current parent wasn't of the right type, so keep looking recursively
return FindParentOfType<T>(parentObj);
}
May be because of the plug-in enviornment I have, this visual tree didn't have that kind of a parent Window, resulting a null handle. So the solution in my case was to find the main window handle of the parent process and give it to CEF. Hope it may help some one with similar situations.
Related
XCB allows us to...
read a window's name (title) via the WM_NAME and _NET_WM_NAME properties
monitor for changes in window properties via XCB_EVENT_MASK_PROPERTY_CHANGE
I'm successfully doing both of these. Specifically, here is how I monitor for changes in the _NET_WM_NAME property of all windows (by subscribing to events on the root window):
/* ... */
const uint32_t list[] = { XCB_EVENT_MASK_PROPERTY_CHANGE };
xcb_change_window_attributes(conn, root_window, XCB_CW_EVENT_MASK, &list);
xcb_flush(conn);
xcb_generic_event_t *evt;
while ((evt = xcb_wait_for_event(conn)))
{
if (evt->response_type == XCB_PROPERTY_NOTIFY)
{
xcb_property_notify_event_t *e = (void *) evt;
/* ... print the window name ... */
}
free(evt);
}
/* ... */
This seems to work fine for the most part, but I've noticed that I don't receive an event when I change tabs within my browser, even though that does change the browser window's title.
Am I doing it wrong or is that not possible with XCB?
Credit for the above code mostly goes to this answer on a related question.
Specifically, here is how I monitor for changes in the _NET_WM_NAME property of all windows (by subscribing to events on the root window):
The code you show does not monitor property changes of all windows. It only monitors for property changes on the root window.
If you want to listen on property changes on all windows... well, it's complicated. You can select for SubstructureNotify. This should give you CreateNotify events whenever a new sub-window is created. For that window, you would again select SubstructureNotify etc to get all windows, recursively.
For each of the windows you found this will, you also want to send a QueryTree request to get its children. You also have to select the events for the child windows which already existed before your program started.
Of course, you should also select for PropertyNotifyMask while you are requesting SubstructureNotify. That way, you should get informed whenever any window changes any property (*).
(*): Well, of course it is possible for something to create a window and immediately change a property. Most likely, this property will be set before you get a chance to ask for PropertyNotify. Thus, if you really want to see all properties, you also need a ListProperties request on the windows after you asked for property changes...
I have a windows form with a button in it. I have 2 threads and i want to change the button name from the other thread. I get an error when i do that.
how can i change the button name?
P.S. I know that a same question alredy posted, but the solution there can't help me. I can't use the Dispatcher, maybe it's because i use .NET 2.0 (I have to...).
delegate void MyDelegate(string x);
void ChangeName(string name)
{
if (this.InvokeRequired)
{
this.Invoke(new MyDelegate(this.ChangeName), new object[]{name});
return;
}
this.button.Text = name;
}
more info here
How to update the GUI from another thread in C#?
you need to look at the:
InvokeRequired and
Invoke
methods on the actual control. InvokeRequired will tell you if you need to do this stuff via invoke (i.e. it's being called from a thread that is not the UIThread) and invoke will perform the action.
it's not that different from Dispatcher except the responsibility falls to the control itself and not some other class.
I am creating a xps document as below.
Assembly assembly = Assembly.GetExecutingAssembly();
//read embedded xpsDocument file
Stream helpStream = assembly.GetManifestResourceStream(resourceNameOfContext);
if (helpStream != null)
{
Package package = Package.Open(helpStream);
string inMemoryPackageName = "memorystream://" + topicName + ".xps";
Uri packageUri = new Uri(inMemoryPackageName);
//Add package to PackageStore
PackageStore.AddPackage(packageUri, package);
docXps = new XpsDocument(package, CompressionOption.Maximum, inMemoryPackageName);
}
return docXps;
When i am trying to get docXps.GetFixedDocumentSequence();
I am getting the above error. Can anyone help?
Thanks,
Your problem has nothing to do with the code surrounding the creation or use of the XPS document. It has everything to do with what thread you are running under.
You will receive the The calling thread must be STA, because many UI components require this error whenever any of the following are attempted on a MTA thread:
You construct any object derived from FrameworkElement (including Controls and Panels)
You construct any object derived from BitmapEffect
You construct any object derived from TextComposition
You construct any object derived from HwndSource
You access the current InputManager
You access the primary KeyboardDevice, StylusDevice, or TabletDevice
You attempt to change the focus on a FrameworkContentElement
You provide mouse, keyboard or IME input to any control that accepts text input
You make WPF content visible or update its layout
You manipulate the visual tree in such a way as to cause a re-evaluation for rendering
Several other changes, mostly having to do with display and input
For example, I received this error last year when I tried to deserialize some XAML that contained <Button> and other WPF objects from within a WCF service. The problem was simple to solve: I just switch to a STA thread to do the processing.
Obviously most work with XPS documents will trigger one or more of the above conditions. In your case I suspect that GetFixedDocumentSequence ends up using TextComposition or one of its subclasses.
No doubt the my solution of switching to a STA thread will also work for you, but first you need to figure out how your code that works with XpsDocuments is getting executed run from a MTA thread. Normally any code from from the GUI (eg a button press) is automatically run in a STA thread.
Is it possible that your code that manipulates XPS Documents may be being executed without a GUI? From a user-created thread? From a WCF service or a web service? From an ASPX page? Track that down and you'll probably find your solution.
If that doesn't work, let us know the details of the path through which GetFixedDocumentSequence is called, so we can diagnose it. The directly surrounding code isn't nearly as important as the call stack and how it is originally being invoked. If it is hard to explain you probably should add a call stack to prevent misunderstandings and help us diagnose the problem further, or tell you how to start a STA thread in your particular situation.
Is your code trying to access the xps doc from a background thread? If this is the case, you'll want to use the dispatcher. Info on that here.
If this doesn't help, could you post the code where you're actually calling GetFixedDocumentSequence()?
When we place a component on a Windows Form, the default behavior for the designer is to serialize a contructor call in the IntializeComponent method of the form.
Is there any way to have a custom serializer output the following code:
if (componentInstance == null)
componentInstance = new componentClass();
instead of just:
componentInstance = new componentClass();
The reason is simply that the component is instantiated before the Form, and I want to pass it to one of the Form's constructors.
The component is designed to allow quick selection of properties (in the same way you add your DataBinding to Controls) at design time, but the call to the constructor in InitializeComponent() assumes I want to create a new instance when in fact, I already have a reference to it. By checking for null, then it would work both at design time and run time.
Thank you.
It's simple really - don't use the Form Designer to add your component to the Winform. Instead manually add a member variable of the component type that you are after into the underlying code (.cs) file and handle it directly in code.
Added in response to your comment
As far as I am aware, there is no way in which you can avoid this behaviour for components placed at design time. You could delete references from initialise components method, but this may be overwritten by the designer at some point.
Taking into account your comment below, then I would suggest that you have a member variable on the form (as suggested above) and then set this to refer to the design time component if the runtime variable is null or the runtime variable if it isn't.
i.e.
CSomeComponentType liveComponent;
...
this.liveComponent = runtimeVariable;
if(this.liveComponent == null)
{
this.liveComponent = this.designTimeComponent;
}
Currently for ASP.Net stuff I use a request model where a context is created per request (Only when needed) and is disposed of at the end of that request. I've found this to be a good balance between not having to do the old Using per query model and not having a context around forever. Now the problem is that in WPF, I don't know of anything that could be used like the request model. Right now it looks like its to keep the same context forever (Which can be a nightmare) or go back to the annoying Using per query model that is a huge pain. I haven't seen a good answer on this yet.
My first thought was to have an Open and Close (Or whatever name) situation where the top level method being called (Say an event handling method like Something_Click) would "open" the context and "close" it at the end. Since I don't have anything on the UI project aware of the context (All queries are contained in methods on partial classes that "extend" the generated entity classes effectively creating a pseudo layer between the entities and the UI), this seems like it would make the entity layer dependent on the UI layer.
Really at a loss since I'm not hugely familiar with state programming.
Addition:
I've read up on using threads, but the
problem I have with a context just
sitting around is error and recovery.
Say I have a form that updates user
information and there's an error. The
user form will now display the changes
to the user object in the context
which is good since it makes a better
user experience not to have to retype
all the changes.
Now what if the user decides to go to
another form. Those changes are still
in the context. At this point I'm
stuck with either an incorrect User
object in the context or I have to get
the UI to tell the Context to reset
that user. I suppose that's not
horrible (A reload method on the user
class?) but I don't know if that
really solves the issue.
Have you thought about trying a unit of work? I had a similar issue where I essentially needed to be able to open and close a context without exposing my EF context. I think we're using different architectures (I'm using an IoC container and repository layer), so I have to cut up this code a bit to show it to you. I hope it helps.
First, when it comes to that "Something_Click" method, I'd have code that looked something like:
using (var unitOfWork = container.Resolve<IUnitOfWork>){
// do a bunch of stuff to multiple repositories,
// all which will share the same context from the unit of work
if (isError == false)
unitOfWork.Commit();
}
In each of my repositories, I'd have to check to see if I was in a unit of work. If I was, I'd use the unit of work's context. If not, I'd have to instantiate my own context. So in each repository, I'd have code that went something like:
if (UnitOfWork.Current != null)
{
return UnitOfWork.Current.ObjectContext;
}
else
{
return container.Resolve<Entities>();
}
So what about that UnitOfWork? Not much there. I had to cut out some comments and code, so don't take this class as working completely, but... here you go:
public class UnitOfWork : IUnitOfWork
{
private static LocalDataStoreSlot slot = Thread.AllocateNamedDataSlot("UnitOfWork");
private Entities entities;
public UnitOfWork(Entities entities)
{
this.entities = entities;
Thread.SetData(slot, this);
}
public Entities ObjectContext
{
get
{
return this.Entities;
}
}
public static IUnitOfWork Current
{
get { return (UnitOfWork)Thread.GetData(slot); }
}
public void Commit()
{
this.Entities.SaveChanges();
}
public void Dispose()
{
entities.Dispose();
Thread.SetData(slot, null);
}
}
It might take some work to factor this into your solution, but this might be an option.