前往Shuct.Net首页

Shudepb PB反编译专家长时间以来,为业内同类软件事实上的唯一选择.细节,彰显专业.态度,决定品质.

关于PowerBuilder的搜索

PowerBuilder – Using C# Visual Objects in PB Classic Applications - CodeProject 10,434,507 members (51,521 online) Sign in Email Password Forgot your password? Sign in using home articles Chapters and Sections> Search Latest Articles Latest Tips/Tricks Top Articles Beginner Articles Technical Blogs Posting/Update Guidelines Article Help Forum Article Competition Submit an article or tip Post your Blog quick answers Ask a Question about this article Ask a Question View Unanswered Questions View All Questions... C# questions ASP.NET questions VB.NET questions C#4.0 questions Javascript questions discussions All Message Boards... Application Lifecycle> Running a Business Sales / Marketing Collaboration / Beta Testing Work & Training Issues Design and Architecture ASP.NET JavaScript C / C++ / MFC> ATL / WTL / STL Managed C++/CLI Adobe Technologies C# Free Tools Objective-C Ruby On Rails Database Hardware & Devices> System Admin Hosting and Servers Java .NET Framework Android Mobile Sharepoint Silverlight / WPF Visual Basic Web Development Site Bugs / Suggestions features CodeProject.TV Discuss CodeProject.TV Component & Service Catalog Competitions News The Insider Newsletter The Daily Build Newsletter Newsletter archive Surveys Product Showcase Research Library CodeProject Stuff community The Insider News The Lounge ? The Weird & The Wonderful The Soapbox Press Releases Who's Who Most Valuable Professionals Company Listings Non-English Language > General Indian Topics General Chinese Topics help What is 'CodeProject'? General FAQ Ask a Question Bugs and Suggestions Article Help Forum Site Map Advertise with us Employment Opportunities About Us Search within: Articles Videos Quick Answers Messages Product Catalog Articles » Web Development » Applications & Tools » Tools with source code Next ArticleBrowse CodeStatsRevisions (5)Alternatives Comments & Discussions (4) PowerBuilder – Using C# Visual Objects in PB Classic Applications By Matt Balent, 22 Jun 2012 0.00 (No votes) Rate this: Please Sign up or sign in to vote. This article will explain how to build a COM visual component in C# using Visual Studio 2010; it is an extension of my earlier example of using the Interop Forms Toolkit to build a Visual Basic COM object. First you need to install the Microsoft Interop Toolkit (available here). Then download the C# Interop Form Toolkit by Leon Langleyben from Codeproject. Installation of this is primarily copying files to the appropriate places based on your Visual Studio install (instructions are provided in Leon’s article). Begin by creating a new project (Visual C#) with the ‘VB6 Interop UserControl’ Template. Give the project a meaningful name, ‘IOPCsharpexample’ is my choice. Visual Studio creates the Solution with a variety of files/references. All of the code will be done in the InteropUserControl.cs file. Opening the InteropUserControl.cs file (right click on the item in the Solution Explorer and choose ‘View Code’) gives this. Clicking on the plus to the left of ‘Interfaces’ expands that code section. Note that there are two interface definitions, one for events and another for properties (and methods). This is one place we need to add to in order to expose the control within Powerscript. To build the actual control, open the Designer window for the InteropUserControl.cs file (right click and choose ‘View Designer’. This gives you the layout of the user control itself. Add a trackbar control from the Tools window. Change some of the trackbar attributes in the Properties display. The changes from the default are Name – TB1, Backcolor – Yellow, Orientation – Vertical, TickFrequency – 10, TickStyle – Both, Maximum – 100, and Margin – 0,0,0,0. Unlike the VB control I demonstrated before, this is a vertical trackbar without any label to display its current value. On the properties view for the trackbar TB1, click on the Events button. This shows a list of the defined events for the control. Double click on the ValueChanged event. This will add a stub for the event on the code page. However, we must also add an initialization for an event handler to the event within the objects declaration so that it will be exposed. Use the same steps to expose the Scroll event on the trackbar. Once finished you can see the events created in bold on the Properties window. Now to complete the C# code refer to the following: using System.ComponentModel; using System.Runtime.InteropServices; using Microsoft.VisualBasic; using System.Windows.Forms; using System.Security.Permissions; using System.Drawing; namespace IOPCsharpexample { #region Interfaces [ComVisible(true), Guid(InteropUserControl.EventsId), InterfaceType(ComInterfaceType.InterfaceIsIDispatch)] public interface __InteropUserControl { [DispId(1)] void Click(); [DispId(2)] void DblClick(); //add additional events visible in VB6 // these events exposed and shown in PB event list [DispId(3)] void tbScroll(); [DispId(4)] void tbValuechanged(); } [Guid(InteropUserControl.InterfaceId), ComVisible(true)] public interface _InteropUserControl { [DispId(1)] bool Visible { [DispId(1)] get; [DispId(1)] set; } [DispId(2)] bool Enabled { [DispId(2)] get; [DispId(2)] set; } [DispId(3)] int ForegroundColor { [DispId(3)] get; [DispId(3)] set; } [DispId(4)] int BackgroundColor { [DispId(4)] get; [DispId(4)] set; } [DispId(5)] Image BackgroundImage { [DispId(5)] get; [DispId(5)] set; } [DispId(6)] void Refresh(); //add additional properties visible in VB6 // PB can call these [DispId(7)] void tbsetbackcolor(int testval); [DispId(8)] int tb1backgroundcolor { [DispId(8)] get; [DispId(8)] set; } [DispId(9)] int tb1value { [DispId(9)] get; [DispId(9)] set; } } #endregion [Guid(InteropUserControl.ClassId), ClassInterface(ClassInterfaceType.None)] [ComSourceInterfaces("IOPCsharpexample.__InteropUserControl")] [ComClass(InteropUserControl.ClassId, InteropUserControl.InterfaceId, InteropUserControl.EventsId)] public partial class InteropUserControl : UserControl, _InteropUserControl { #region VB6 Interop Code #if COM_INTEROP_ENABLED #region "COM Registration" //These GUIDs provide the COM identity for this class //and its COM interfaces. If you change them, existing //clients will no longer be able to access the class. public const string ClassId = "e7c6c97a-af38-4d57-9980-9edd60e1b45c"; public const string InterfaceId = "2aab63cc-a9df-4197-89f4-44150a746301"; public const string EventsId = "1eeca2b9-97ac-4c1c-8dc1-770c941c8ebd"; //These routines perform the additional COM registration needed by ActiveX controls [EditorBrowsable(EditorBrowsableState.Never)] [ComRegisterFunction] private static void Register(System.Type t) { ComRegistration.RegisterControl(t); } [EditorBrowsable(EditorBrowsableState.Never)] [ComUnregisterFunction] private static void Unregister(System.Type t) { ComRegistration.UnregisterControl(t); } #endregion #region "VB6 Events" //This section shows some examples of exposing a UserControl's events to VB6. Typically, you just //1) Declare the event as you want it to be shown in VB6 //2) Raise the event in the appropriate UserControl event. public delegate void ClickEventHandler(); public delegate void DblClickEventHandler(); public new event ClickEventHandler Click; //Event must be marked as new since .NET UserControls have the same name. public event DblClickEventHandler DblClick; private void InteropUserControl_Click(object sender, System.EventArgs e) { if (null != Click) Click(); } private void InteropUserControl_DblClick(object sender, System.EventArgs e) { if (null != DblClick) DblClick(); } #endregion #region "VB6 Properties" //The following are examples of how to expose typical form properties to VB6. //You can also use these as examples on how to add additional properties. //Must Shadow this property as it exists in Windows.Forms and is not overridable public new bool Visible { get { return base.Visible; } set { base.Visible = value; } } public new bool Enabled { get { return base.Enabled; } set { base.Enabled = value; } } public int ForegroundColor { get { return ActiveXControlHelpers.GetOleColorFromColor(base.ForeColor); } set { base.ForeColor = ActiveXControlHelpers.GetColorFromOleColor(value); } } public int BackgroundColor { get { return ActiveXControlHelpers.GetOleColorFromColor(base.BackColor); } set { base.BackColor = ActiveXControlHelpers.GetColorFromOleColor(value); } } public override System.Drawing.Image BackgroundImage { get{return null;} set { if(null != value) { MessageBox.Show("Setting the background image of an Interop UserControl is not supported, please use a PictureBox instead.", "Information"); } base.BackgroundImage = null; } } #endregion #region "VB6 Methods" public override void Refresh() { base.Refresh(); } //Ensures that tabbing across VB6 and .NET controls works as expected private void InteropUserControl_LostFocus(object sender, System.EventArgs e) { ActiveXControlHelpers.HandleFocus(this); } public InteropUserControl() { //This call is required by the Windows Form Designer. InitializeComponent(); //' Add any initialization after the InitializeComponent() call. this.DoubleClick += new System.EventHandler(this.InteropUserControl_DblClick); base.Click += new System.EventHandler(this.InteropUserControl_Click); this.LostFocus += new System.EventHandler(InteropUserControl_LostFocus); this.ControlAdded += new ControlEventHandler(InteropUserControl_ControlAdded); //////// new events to expose to PB this.TB1.ValueChanged += new System.EventHandler(TB1_ValueChanged); this.TB1.Scroll += new System.EventHandler(TB1_Scroll); ////////// //'Raise custom Load event this.OnCreateControl(); } [SecurityPermission(SecurityAction.LinkDemand, Flags =SecurityPermissionFlag.UnmanagedCode)] protected override void WndProc(ref System.Windows.Forms.Message m) { const int WM_SETFOCUS = 0x7; const int WM_PARENTNOTIFY = 0x210; const int WM_DESTROY = 0x2; const int WM_LBUTTONDOWN = 0x201; const int WM_RBUTTONDOWN = 0x204; if (m.Msg == WM_SETFOCUS) { //Raise Enter event this.OnEnter(System.EventArgs.Empty); } else if( m.Msg == WM_PARENTNOTIFY && (m.WParam.ToInt32() == WM_LBUTTONDOWN || m.WParam.ToInt32() == WM_RBUTTONDOWN)) { if (!this.ContainsFocus) { //Raise Enter event this.OnEnter(System.EventArgs.Empty); } } else if (m.Msg == WM_DESTROY && !this.IsDisposed && !this.Disposing) { //Used to ensure that VB6 will cleanup control properly this.Dispose(); } base.WndProc(ref m); } //This event will hook up the necessary handlers private void InteropUserControl_ControlAdded(object sender, ControlEventArgs e) { ActiveXControlHelpers.WireUpHandlers(e.Control, ValidationHandler); } //Ensures that the Validating and Validated events fire appropriately internal void ValidationHandler(object sender, System.EventArgs e) { if( this.ContainsFocus) return; //Raise Leave event this.OnLeave(e); if (this.CausesValidation) { CancelEventArgs validationArgs = new CancelEventArgs(); this.OnValidating(validationArgs); if(validationArgs.Cancel && this.ActiveControl != null) this.ActiveControl.Focus(); else { //Raise Validated event this.OnValidated(e); } } } #endregion #endif #endregion //Please enter any new code here, below the Interop code /////////// events to expose to PB public delegate void tbValueChangedEventHandler(); public event tbValueChangedEventHandler tbValuechanged; private void TB1_ValueChanged(object sender, System.EventArgs e) { if (tbValuechanged != null) { tbValuechanged(); } } public event tbScrollEventHandler tbScroll; public delegate void tbScrollEventHandler(); private void TB1_Scroll(object sender, System.EventArgs e) { if (tbScroll != null) { tbScroll(); } } //////////// //method to call from PB public void tbsetbackcolor(int testval) { Color myColor = ColorTranslator.FromWin32(testval); //translate numeric color TB1.BackColor = myColor; //set background of trackbar BackColor = myColor; // set background of user control } /////////// // Property get/set to call from PB public int tb1backgroundcolor { get { return ActiveXControlHelpers.GetOleColorFromColor(TB1.BackColor); } set { TB1.BackColor = ActiveXControlHelpers.GetColorFromOleColor(value); } } public int tb1value { get { return TB1.Value; } set { TB1.Value = value; } } /////////// } } Note that the two event stubs created by doubleclicking on the event name in the IDE were moved to the end of the class, after the final ‘#endregion’ lable so most of the code outside the interface section is together. In a nutshell to expose the event to PB you have to: add the events after the InitializeComponent call on the class create a public eventhandler delegate create a public event which the delegate references code the event (double clicking on the control – event list gives you the event ‘skeleton’ add the event to the event interface To code a property or method which can be called from PB you have to: create a public method with parameters and return values (if needed) OR a public property with both a get and set section. add the method/property to the property interface Important Note: Unlike the default for Visual Basic (or PowerBuilder for that matter), C# is strongly typed. This means that a method with the name ‘MyEvent’ is not the same as ‘myevent’, ‘Myevent’ or ‘myEvent’. Quite often your code will compile file, but when you try to use your component in PB you will crash and burn. When this is built in Visual Studio a DLL is created and registered on the machine. If you want to take the dll to a different machine you will have to manually register the dll in order to use it in PowerBuilder. Using the control in PowerBuilder So now to add the control in PowerBuilder you click on the Insert OLE control icon, choose the Insert Control tab and then the control from the control list. The example app created to demonstrate the VB.NET component is expanded to include the C# component as well. A few more PB controls are added to the form which results in this. The code in the clicked event of the Set Color button follows: long ll_vb_color, ll_cs_color // set the desired color on the controls IF sle_1.text = string(RGB(0,174,221)) THEN ll_vb_color = 15780518 ll_cs_color = RGB(168,255,168) ELSE ll_vb_color = RGB(0,174,221) ll_cs_color = RGB(196,240,16) END IF // call method on VB .Net control ole_3.object.event tbSetBackColor(ll_vb_color) // call method on C# .Net control ole_2.object.tbSetBackColor(ll_cs_color) // get the color value using the 'getter' method in VB .Net control sle_1.text = string(ole_3.object.tb1backgroundcolor()) // get the color value using the 'getter' method in C# .Net control sle_2.Text = string(ole_2.object.tb1backgroundcolor()) The only difference in the method calls to the controls (tbSetBackColor method) is in VB you qualify it as an event. The code in the tbvaluechanged event on the C# control is st_4.text = string(ole_2.object.tb1value()) Which is calling the C# get method of the tb1value property. In the tbscroll event on the control is the following: long ll_val, ll_color //report on the current value of the control ll_val = ole_2.object.tb1value() //move the PB control vtb_1.position = ll_val As is the case for the VB control, you must have some code in the events you expose or you will get an unhandled exception error. Running the sample application. Clicking the Set Color button changes the .NET controls Moving the VB control Moving the C# control The PowerBuilder code was written in version 12.5.1. Within the csharpinteroppb are export files if you are working with an earlier version. License This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL) About the Author Matt Balent Software Developer (Senior) United States PowerBuilder MVP based in Charlotte, NC Article Top Comments and Discussions You must Sign In to use this message board. Search this forum Profile popups Spacing RelaxedCompactTight Noise Very HighHighMediumLowVery Low Layout NormalOpen TopicsOpen AllThread View Per page 102550 First Prev Next PowerBuilder through C# coding khanzzirfan31-Oct-12 8:51 Hi Matt, The above written article in C# is great and really really helped me alot. First thank you for sharing the article. I have a one question, regarding PowerBuilder datawindow retrieve for ole object which I want to trace through C#. Here is what exact where I'm stuck in figuring out the retrieve option. 1) I have created line graph exactly as you explained for creating the "track bar" which is VB6 Interop control. The graph pulls the data through SQL stored procedure which takes one argument/parameter (i.e Id). 2)I have created a new OLE datawindow (adding stored procedure to it) and placed the above created graph control in the PowerBuilder datawindow. 3) So, normal datawindow funtionality for Ole objects is, it retrieve the data through stored procedure and passes the data through "target data (datawindow property)" to Ole object. 4) I'm stuck here, where i need to capture the data (for example 'id' value) when datawindow stored procedure passes the id to Ole object. If you please can help me in the above case would be really help full. Your help is much appreciated. Looking forward to you. Thank you. Note: Also there is code which sybase recommend is to use the sybase.datawindow.net library ( need to buy the library) to grab the data when data window retrieve passes the data to Ole target data. VB CODE settings = dw.Describe("ole1.target") I dont know how much the above code is help full, but I really dont want to buy the library for now. Irfan Sign In·View Thread·Permalink Re: PowerBuilder through C# coding Matt Balent2-Nov-12 5:42 I'm unsure about your question. You should have a retrieval argument defined for the datawindow. You send the value to the datawindow when you issue a retieve ( ie. dw_1.retrieve(123) ). In this case you know the argument. If you are needing to see the data brought back into the datawindow from the retrieve you can use something similar to: any la_any; la_any = dw_1.object.data This will give you an array of data structures whose members match the column datatypes. Matt Sign In·View Thread·Permalink Re: PowerBuilder through C# coding khanzzirfan2-Nov-12 9:42 Hi Matt, Thank you for you prompt reply. Actually the question is, while datawindow is retrieve is called, i want to capture that data. The retrieve is through data window it self, not calling through the window using the code dw1.object.data. When retrieve is called, I want to know what Id has been passed through argument in data window. If I can capture that Id in C# that would be really great. Please let me know if you have any ideas around this.. If my question still doesn't explain much to you, I can send you in a detail information with images in it. If you could forward me email please. Really thank you for looking into my question. Please help me in above case well. THank you. Irfan Sign In·View Thread·Permalink 2 similar entries... Sandeep Mewara22-Jun-12 2:24 There is not much difference from this blog entry: http://www.codeproject.com/script/Articles/ArticleVersion.aspx?waid=20411&aid=408620[^] Both can be clubbed together. Sandeep Mewara [My last article]: Server side Delimiters in ASP.NET[^] Sign In·View Thread·Permalink Last Visit: 31-Dec-99 18:00 Last Update: 3-Mar-14 13:52Refresh1 General News Suggestion Question Bug Answer Joke Rant Admin Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages. About Article A Technical Blog, originally posted at http://anvil-of-time.com/wordpress/PowerBuilder/PowerBuilder-using-c-visual-objects-in-pb-classic-applications/ This article will explain how to build a COM visual component in C# using Visual Studio 2010; it is an extension of my earlier example of using the Interop Forms Toolkit to build a Visual Basic COM object. First you need to install the Microsoft Interop Toolkit (available here). Then download the C# Type Technical Blog Licence CPOL First Posted 22 Jun 2012 Views 7,737 Bookmarked 4 times C#WindowsCOMIntermediate Top News News on the future of C# as a language Get the Insider News free each morning. Related Videos Related Articles Case Study: Refactoring a PowerBuilder Classic Application Bye Bye Clip Window; Hello Snippets RESTful Web Services: A Quick-Start How-to Guide - Part 1 Refactoring PowerBuilder Applications Sybase PowerBuilder Meets Microsoft .NET PowerBuilder – Using .Net Visual Controls in PB Classic Applications Merging Newer Technology into an Existing Code Line Web Services DataWindows Peering Behind the PowerBuilder .NET Assembly Curtain RESTful Web Services: A Quick-Start How-to Guide - Part 2 Call C# assembly and its method in PowerBuilder Refactoring Corner: Partitioning DataWindow Technology PowerBuilder ‘Gotcha’ – Grid Datawindows with Picture Controls Slicing the Pie with PowerBuilder .NET 12.1 EBF Project Partitioning Introduction to Pocket PC Development The Missing Link Gotcha: PB Deployment – SYSTEM var not supported error Simple FilmStrip Control Getting to the Top of the Pecking Order COM+ Object Pooling Related Research Learn Agile: Ten Tips for Launching and Testing High Quality Apps for the American Market Fine-Tuning the Engines of SMB Growth: 4 strategies for growing your business The Essential Guide to Mobile App Testing: Tips for Developers in USA & Canada In-The-Wild Testing: How to Ensure Your Apps Work in the Real World Permalink | Advertise | Privacy | Mobile Web02 | 2.8.140227.1 | Last Updated 22 Jun 2012 Article Copyright 2012 by Matt BalentEverything else Copyright © CodeProject, 1999-2014 Terms of Use Layout: fixed | fluid