Ironpython with pycharm: Drawing and Forms - winforms

This is probably a very noob question. I am trying to get some basic code from sharpdevelop into Pycharm. The code basically just draws a window and place some fields and buttons using Windows forms. I've set the interprter in Pycharm to be Ironpython. There seems to be something wrong with the import statements. When I run the following (Which is just a copy paste from code that is perfectly working in sharpdevelop):
import System.Drawing
import System.Windows.Forms
class MainForm(Form):
def __init__(self):
self.InitializeComponent()
def InitializeComponent(self):
self._checkBox1 = System.Windows.Forms.CheckBox()
self._comboBox1 = System.Windows.Forms.ComboBox()
self._label1 = System.Windows.Forms.Label()
#rest of code ...
I get the following message
ImportError: No module named Drawing

You will need to add a reference to the DLLs. It's three lines:
import clr
clr.AddReference("System.Drawing")
clr.AddReference("System.Windows.Forms")
SharpDevelop takes care of adding the references in Program.py (the file that runs). It imports the MainForm class, instantiates it, and displays the form.
Since I am assuming this is the file you run, you will need to add the references within the same file.

Related

Add column heading (and corresponding property) to Wagtail index view

My team and I have created a section to allow our company to add landing pages. We'd like to include some additional columns to the index view of the associated model, as illustrated in this image.
I've found a few old posts (2014-ish) that indicate this wasn't possible, but I can't find anything newer that makes that claim invalid. Is it possible to do this, and if so can someone point me in the right direction?
If you are willing to patch the view and template for the Page Explorer, you should be able to do this. My group isn't patching the Page Explorer so I don't have example code for that but our general approach is as follows:
We have a django app called wagtail_patches which is listed in our INSTALLED_APPS before the wagtail apps.
In wagtail_patches/apps.py we have:
from django.apps import AppConfig
class WagtailPatchesConfig(AppConfig):
name = 'wagtail_patches'
verbose_name = 'Wagtail Patches'
ready_is_done = False
def ready(self):
"""
This function runs as soon as the app is loaded. It executes our monkey patches to various parts of Wagtail
that change it to support our architecture of fully separated tenants.
"""
# As suggested by the Django docs, we need to make absolutely certain that this code runs only once.
if not self.ready_is_done:
# The act of performing this import executes all the code in monkey_patches.
from . import monkey_patches
# Unlike monkey_patches, the code of wagtail_hook_patches is in the function patch_hooks().
from .wagtail_hook_patches import patch_hooks
patch_hooks()
self.ready_is_done = True
else:
print("{}.ready() executed more than once! This method's code is skipped on subsequent runs.".format(
self.__class__.__name__
))
Then in wagtail_patches/monkey_patches.py we import the module to be patched, then write a new method, and then replace the stock version with the new method. For example:
from wagtail.admin.forms.collections import CollectionForm
def collection_form_clean_name(self):
if <weird custom condition>:
raise ValidationError('some error message')
CollectionForm.clean_name = collection_form_clean_name
Overriding templates is just like normal django template overriding, place your customized version of some file in a folder hierarchy matching it's usual position within Wagtail.
You can do this with ModelAdmin for a specific model, but it won't appear in the Pages Explorer view as in your screenshot. Instead, it will appear in a new menu item on the left sidebar. I also find that Hooks is a great place to store this logic. Just be aware of how ModelAdmin differs from modeladmin. The Bakery Demo has some good examples of how this all works.

How to handle Solutions, Projects and their contents in a VisualStudio extension

In short:
I'm new to VisualStudio Extensibility and my goal is to create an extension with a ToolWindow (which already works) showing different views for each context of a VisualStudio solution, i. e. a view for the solution, a view for a project etc.. The window should be opened by clicking on a context menu entry in the context menus of the Solution Explorer, Class View, Object Browser and (ideally) any other window showing contents like projects, namespaces, classes etc..
After searching I found a lot of information, but for some points I couldn't find very helpful information. How do I ...
... create a context menu item for the VisualStudio views?
... get the currently open solution as an instance in code?
... get the projects of the solution and their contens as instances in code?
... add/remove items to/from a solution/project/class/... in code?
... react to selection changes in the Solution Explorer?
What I've done, so far:
I read the docs for Starting to Develop Visual Studio Extensions and downloaded the VSSDK-Extensibility-Samples. Especially the WPF_Toolwindow example was interesting for my purposes, so I built and ran it, which was successful, so far. Another interesting sample would have been the WPFDesigner_XML, but it always throws a NullReferenceException, so I decided to stick with the former ToolWindow, which is completely fine, for now.
Furtermore, I tried to understand the example by having a close look at each file in the project, running it in the debugger and analyzing what happened. I'm confident I understood it, but am also open for corrections of my possibly misguided thoughts following.
Now, I have created a new project, based on the WPF_Toolwindow sample, renamed and adapted to my needs (basically, I created new GUIDs, renamed the namespaces and removed things I won't use). This extension still works in the debugger. I even uninstalled everything from the experimental instance and debugged the extension from scratch.
What I try to achieve:
Have the ToolWindow load a specific view/viewmodel, when the selection changes in the Solution Explorer (or any other VisualStudio view). Alternatively, there should be a context menu item for every node's context menu in the Solution Explorer tree (or any other VisualStudio view).
Get the currently open solution, the containing projects and basically everything from the Solution Explorer's content as instances processable in my viewmodel. I need to properly add/remove
classes/structs/enums to/from
a folder in a project
a namespace
properties/fields to/from a class/struct
Generate code based on information of the solution and add the file properly to a project.
Does anyone know of examples for something like this or can anyone give me some hints, where I can find further information? Any help would be appreciated. Thanks in advance.
(1) The items already have a context menu and I want to add a new command to this menu.
if you want to add a sub menu to the context menu, the following link provide a complete sample
https://github.com/visualstudioextensibility/VSX-Samples/tree/master/CommandSubmenu
(3) Yes, basically adding a file to a project without manually manipulating the project file would be nice.
You can add the file to project via Project.ProjectItems.AddFromFile, and the following provide a sample for your reference.
https://www.mztools.com/Articles/2014/MZ2014009.aspx
Update:
I select a project and a similar event is fired. Are there such events I can subscribe to?
You could use IVsMonitorSelection to implement. here is the code which retrieve related project path for your reference.
IntPtr hierarchyPointer, selectionContainerPointer;
Object selectedObject = null;
IVsMultiItemSelect multiItemSelect;
uint projectItemId;
IVsMonitorSelection monitorSelection =
(IVsMonitorSelection)Package.GetGlobalService(
typeof(SVsShellMonitorSelection));
monitorSelection.GetCurrentSelection(out hierarchyPointer,
out projectItemId,
out multiItemSelect,
out selectionContainerPointer);
IVsHierarchy selectedHierarchy = Marshal.GetTypedObjectForIUnknown(
hierarchyPointer,
typeof(IVsHierarchy)) as IVsHierarchy;
if (selectedHierarchy != null)
{
ErrorHandler.ThrowOnFailure(selectedHierarchy.GetProperty(
projectItemId,
(int)__VSHPROPID.VSHPROPID_ExtObject,
out selectedObject));
}
Project selectedProject = selectedObject as Project;
string projectPath = selectedProject.FullName;
For more information about the usage, please refer to:
https://www.mztools.com/articles/2007/mz2007024.aspx

ActiveX control in ironpython windows form

I'm having difficulties with a set of activeX controls used for automation of lab instruments. I've got them all to work in VB, in forms applications - as they won't work in console applications. My company is working mainly with python and there would thus be a great advantage in writting our drivers in python, mainly for lims integration.
As such, I have tried to embed my activeX controls within ironpython windows forms. I've tried two different ways of introducing my controls in the forms:
1) with clr referencing the Ax dll after using AxImp on the original ocx. Then I add my instance of the control as a form control and try to run it from there. It throws System.Windows.Forms.AxHost+InvalidActiveXStateException.
import clr
clr.AddReferenceToFileAndPath(r"C:\dlls\AxVCode3Lib.dll")
clr.AddReferenceByPartialName("System.Windows.Forms")
import System.Windows.Forms as Forms
import AxVCode3Lib
class activeXform(Forms.Form):
def __init__(self):
a = AxVCode3Lib.AxVCode3()
self.Controls.Add(a)
for i in self.Controls:
r = i.Initialize("serial")
print r
form = activeXform()
raw_input(">exit")
2) Using SystemReflection and the ProgID, which throws a generic "Exception has been thrown by the target of an invocation". The following code was introduced in a basic ironpython windows form, however I was not able to add those objects as form controls.
import System.Type
import System.Reflection
import System.Array
oType = System.Type.GetTypeFromProgID("VCODE3.VCode3Ctrl.1")
o = System.Activator.CreateInstance(oType)
args = System.Array[str](['serial'])
try:
r = oType.InvokeMember("Initialize", System.Reflection.BindingFlags.InvokeMethod, None, o, args)
print r
except Exception as e:
print e
Now I suspect both those examples fail due to some properties missing in my forms. However I can't figure out what it is, in particular in case 1 when the instance is actually added as a control, it seems I am very close.
You cannot use the methods of the ActiveX control until its native handle is created. In other words, not until after you call the form's Show() method.
Make sure you get the basic outline of a Winforms application correct, peek in the Program.cs source code file of a sample C# Winforms app. The Application.Run() call is essential. Use the form's Load event (or override OnLoad) as the first event where you can actually start using the control.

How do I import the white project into an IronPython program?

I am working on some UI automation software and just recently moved the project from Python to IronPython since the requirements for this project state it will only be used in a Windows environment. However, I need to automated the UI of a program that uses Windows Presentation Foundation (WPF). I found this one library that looks like it might be useful called White.
http://white.codeplex.com/
So I would like to use this in my IronPython program but all the example code I have been seeing so far for importing modules written in C# or with a C# interface has been for the Microsoft/Windows built-ins. I figured I should be able to reference it since you can do it with IronRuby according to this article.
http://www.natontesting.com/2010/02/17/how-to-test-a-wpf-app-using-ironruby-and-white/
However, I have to imagine the means/syntax by which IronRuby would import/reference White is very different than how IronPython would do it. I have also found posts by other developers saying they are using IronPython and White, but can't find a post that includes the code to actually make the reference to White. How would I go about this?
import clr
clr.AddReference("White.Core")
clr.AddReference("White.NUnit")
from White.NUnit import *
from White import *
from White.Core import *
from White.Core.Configuration import *
from White.Core.UIItems import *
from White.Core.UIItems.WindowItems import *
from White.Core.UIItems.ListBoxItems import *
from White.Core.UIItems.Container import *
from White.Core.UIItems.Finders import *
from White.Core.Factory import *
from White.Core.Finder import *
from White.Core.AutomationElementSearch import *
from White.Core.WindowsAPI import *
Then use the white api as normal.
app = Application.Attach(proc)
win = app.GetWindow('Window Caption')
print win.Name
box = win.Get[MultilineTextBox]('textBoxId')
print box.Text
IronPython is capable of addressing any CLR assembly using the following:
import clr
clr.AddReference("AssemblyName")
Because the white project is .NET based this will work. To use objects from the assembly:
from AssemblyName import *
(of course you can use a subset here)
Then simply instantiate and use your objects:
from System.Collections import BitArray
ba = BitArray(5)
ba.Set(0, True) # call the Set method
ba[0]
This documentation should help.

Change Default Winform Icon Across Entire App

Can I change the default icon used on a Winform?
Most of my forms have their icon property set to a custom icon. For the few forms that slip through the cracks, I don't want the generic "hey look, he made this in visual studio" icon.
One solution is to tediously check every one of my forms to make sure they either have a custom icon set or have ShowIcon set to False.
Another solution is to have every one of my forms inherit from a base class that sets a custom icon in the constructor.
Aside from those solutions, what other options do I have?
EDIT:
I was hoping there would be a way to replace the source of the stock icon with my own. Is it in a resource file somewhere? Or is it embedded in a .NET dll that I can't (or really, really shouldn't) modify?
BOUNTY EDIT:
Is there a way to accomplish this without editing or writing a single line of code? I don't care how impractical, complicated, waste-of-time the solution is... I just want to know if it's possible. I need to satisfy my curiosity.
The default icon is embedded in the winforms dll - looking at reflector (DefaultIcon) it is:
defaultIcon = new Icon(typeof(Form), "wfc.ico");
There is no magic in there that checks another common location, so you can't do it without changing code.
You could always embrace the forces of darkness with field-based reflection? Note: this is hacky and brittle. On your own head! But it works:
[STAThread]
static void Main() {
// pure evil
typeof(Form).GetField("defaultIcon",
BindingFlags.NonPublic | BindingFlags.Static)
.SetValue(null, SystemIcons.Shield);
// all forms now default to a shield
using (Form form = new Form()) {
Application.Run(form);
}
}
To do it properly; two common options;
a base Form class which has the icon set
a factory Form method - perhaps something like:
code:
public static T CreateForm<T>() where T : Form, new() {
T frm = new T();
frm.Icon = ...
// any other common code
return frm;
}
Then instead of:
using(var frm = new MySpecificForm()) {
// common init code
}
Something like:
using(var frm = Utils.CreateForm<MySpecificForm>()) {
}
Of course - that isn't much prettier! Another option might be a C# 3.0 extension method, perhaps as a fluent API:
public static T CommonInit<T>(this T form) where T : Form {
if(form != null) {
form.Icon = ...
//etc
}
return form;
}
and
using(var frm = new MySpecificForm().CommonInit()) {
// ready to use
}
This is then just a .CommonInit() away from your existing code.
The base class option is the one that we use.
If you are looking for an alternative (not necessarily good ones), you could:
1. Use IOC to instantiate all of your forms and modify the IOC container to set the application icon.
2. Use AOP to insert code into all of the forms that sets the application icon.
Personally, I'd just use the base class...
My useful answer:
No
Would be a nice feature for microsoft to implement though, since most apps use the same icon across the entire application.
If you want to update all the icons by another one, you can build a small app that edits all the *.Designer.vb files (in vb.net) and adding the folowing line to InitializeComponent:
Me.Icon = New System.Drawing.Icon("C:\PathTo\icon.ico")
Hope it helps.
If all your forms are in just one project then you can take the dll of the project and use reflection to get every type in the dll. If the type derives from Form you can set the type's Icon property to whatever you want. I am not sure what the performance overhead will be if the project is very big.

Resources