360 likes | 724 Views
„Gesammelte Werke“ PowerBuilder Tipps und Tricks und sonstiges aus der „normalen“ Client-Server Entwicklung. Ludwin Feiten, Christoph Menken Power People. Teil 2. Tipps & Tricks im Web .net Komponente via ComWrapper Powerbuilder in SAP Business One . Fahrplan.
E N D
„Gesammelte Werke“PowerBuilder Tipps und Tricks und sonstiges aus der „normalen“ Client-Server Entwicklung Ludwin Feiten, Christoph Menken Power People Teil 2
Tipps & Tricks im Web • .net Komponente via ComWrapper • Powerbuilder in SAP Business One Fahrplan Tipps & Tricks 2
powerbuilder.codexchange.sybase.com/ • pbdj.sys-con.com/ • www.pbdr.com/pbtips/ • www.rgagnon.com/howto.html • www.softtreetech.com/hightech/tips.htm • www.topwizprogramming.com/ • www.devx.com/getHelpOn/Door/11957 • www.teamsybase.com/ • members.cox.net/bdick/PbStuff.htm • s.webring.com/hub?ring=pbring • www.teamsybase.com/webring/webring.html • www.powerpeople.de Tipps & Tricks im Web (Auszug) Tipps & Tricks 2
Neue Klassenbibliothek (Class Library) erzeugen .net Komponente via ComWrapper Tipps & Tricks 2
Klasse und alle zugehörigen Referenzen umbenennen .net Komponente via ComWrapper Tipps & Tricks 2
.net Komponente via ComWrapper Tipps & Tricks 2
.net Komponente via ComWrapper Tipps & Tricks 2
.net Komponente via ComWrapper Tipps & Tricks 2
.net Komponente via ComWrapper Tipps & Tricks 2
set dnf=C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727 set sdk=D:\Programme\Microsoft Visual Studio 8\SDK\v2.0\Bin %dnf%\regasm $(TargetFileName) /regfile:$(TargetName).reg %sdk%\gacutil /i "$(TargetPath)" .net Komponente via ComWrapper Tipps & Tricks 2
using System; using System.Collections.Generic; using System.Text; using System.Net.Mail; namespace DotNetSMTP { public class DotNetSMTP { private String senderName; public String SenderName { get { return senderName; } set { senderName = value; } } private String senderEmail; private String smtpServer; private String recipientEmail; private String subject; private String ccEmail = ""; private String bccEmail = ""; private bool isHTML = false; private String messageText; .net Komponente via ComWrapper Tipps & Tricks 2
public void sendMail() { SmtpClient smtpClient = new SmtpClient(); MailMessage message = new MailMessage(); MailAddress fromAddress = new MailAddress(senderEmail, senderName); smtpClient.Host = smtpServer; smtpClient.Port = 25; message.From = fromAddress; message.To.Add(recipientEmail); message.Subject = subject; if (!ccEmail.Equals("")) { message.CC.Add(ccEmail); } if (!bccEmail.Equals("")) { message.Bcc.Add(ccEmail); } message.IsBodyHtml = isHTML; message.Body = messageText; smtpClient.Send(message); } } } .net Komponente via ComWrapper Tipps & Tricks 2
DLL erstellen • Registryeintrag hinzufügen REGEDIT4 [HKEY_CLASSES_ROOT\DotNetSMTP.DotNetSMTP] @="DotNetSMTP.DotNetSMTP" [HKEY_CLASSES_ROOT\DotNetSMTP.DotNetSMTP\CLSID] @="{43C9C58D-A6F4-3D41-A65D-6E0D23EE4249}" [HKEY_CLASSES_ROOT\CLSID\{43C9C58D-A6F4-3D41-A65D-6E0D23EE4249}] @="DotNetSMTP.DotNetSMTP" [HKEY_CLASSES_ROOT\CLSID\{43C9C58D-A6F4-3D41-A65D-6E0D23EE4249}\InprocServer32] @="mscoree.dll" "ThreadingModel"="Both" "Class"="DotNetSMTP.DotNetSMTP" "Assembly"="DotNetSMTP, Version=1.0.0.0, Culture=neutral, PublicKeyToken=7090f4c6a1c37793" "RuntimeVersion"="v2.0.50727" [HKEY_CLASSES_ROOT\CLSID\{43C9C58D-A6F4-3D41-A65D-6E0D23EE4249}\InprocServer32\1.0.0.0] "Class"="DotNetSMTP.DotNetSMTP" "Assembly"="DotNetSMTP, Version=1.0.0.0, Culture=neutral, PublicKeyToken=7090f4c6a1c37793" "RuntimeVersion"="v2.0.50727" [HKEY_CLASSES_ROOT\CLSID\{43C9C58D-A6F4-3D41-A65D-6E0D23EE4249}\ProgId] @="DotNetSMTP.DotNetSMTP" [HKEY_CLASSES_ROOT\CLSID\{43C9C58D-A6F4-3D41-A65D-6E0D23EE4249}\Implemented Categories\{62C8FE65-4EBB-45E7-B440-6E39B2CDBF29}] .net Komponente via ComWrapper Tipps & Tricks 2
Testprogramm in C# erstellen .net Komponente via ComWrapper Tipps & Tricks 2
Die DotNetSMTP.dll als Referenz hinzufügen .net Komponente via ComWrapper Tipps & Tricks 2
Einen Button hinzufügen • Im clicked-Event folgenden Code hinzufügen: DotNetSMTP.DotNetSMTP smtpclient = new DotNetSMTP.DotNetSMTP(); smtpclient.SenderName = "Christoph Menken"; smtpclient.SenderEmail = "christoph.menken@gmx.de"; smtpclient.SmtpServer = "smtp.gmx.de"; smtpclient.RecipientEmail = "christoph.menken@gmx.de"; smtpclient.MessageText = "This is a test, this is only a test."; smtpclient.Subject = "Dot Net via COM is cool"; smtpclient.sendMail(); .net Komponente via ComWrapper Tipps & Tricks 2
Im Powerbuilder: integer li_rc oleobject lole_smtp lole_smtp = CREATE oleobject li_rc = lole_smtp.ConnectToNewObject ( "DotNetSMTP.DotNetSMTP" ) if li_rc = 0 then lole_smtp.SenderName = "Christoph Menken" lole_smtp.SenderEmail = "christoph.menken@gmx.de" lole_smtp.RecipientEmail = "christoph.menken@gmx.de" lole_smtp.SmtpServer = "smtp.gmx.de" lole_smtp.MessageText = "This is a test, this is only a test." lole_smtp.Subject = "Dot Net via COM is cool" else MessageBox( parent.title, & "Error calling DotNetSMTP via COM: " + string(li_rc) ) end if .net Komponente via ComWrapper Tipps & Tricks 2
Kundenauftrag der Be.as GmbH • Be.as ist eine Erweiterung des SAP Business One (SBO) • Vorteile: • Look&Feel wie SBO • Verwendung derselben Datenbank und der SBO DI-API • Leichte Erweiterungsmöglichkeit durch eigene PSR-basierte Skriptsprache • Problem: Extra Programm PB als Add-On Tipps & Tricks 2
Lösung: SBO UI-API • COM+Objekt • Add-On in SBO • Integration in die SBO Eventsteuerug • Problem: Powerbuilder unterstüzt keine Implementation der Events, wie z.B. VisualBasics „with events“ PB als Add-On Tipps & Tricks 2
SAP Business One • Lösung: PBNI Erstellen eines PBNI COM-Objekt, welches das SBO-UI-COM-Objekt verwendet und die Events in PB zur Verfügung stellt SBO UI API Registrierung Triggert Events PB PBNI-COM-Objekt PB als Add-On Tipps & Tricks 2
Beispiel: PBNIOLEObject • Einfaches exemplarisches Beispiel • Integration eines PB-Programms in MS Word • von Bruce Armstrong PB als Add-On Tipps & Tricks 2
PBXEXPORT LPCTSTR PBXCALL PBX_GetDescription() { static const TCHAR desc[] = { "class n_cpp_oleobject from oleobject\n" "function integer CaptureEvents() \n" "function integer ReleaseEvents() \n" "event startup pbm_custom01 \n" "event quit pbm_custom02 \n" "event documentchange pbm_custom03 \n" "end class \n" }; return desc ; } PB als Add-On Tipps & Tricks 2
PBXEXPORT PBXRESULT PBXCALL PBX_CreateNonVisualObject( IPB_Session* pbsession, pbobject pbobj, LPCSTR className, IPBX_NonVisualObject **obj ) { if ( strcmp( className, "n_cpp_oleobject" ) == 0 ) { *obj = new COLEObject() ; return PBX_OK ; } ; *obj = NULL ; return PBX_E_NO_SUCH_CLASS ; } PB als Add-On Tipps & Tricks 2
BEGIN_DISPATCH_MAP(CEventSink, CCmdTarget) DISP_FUNCTION(CEventSink, "Startup", Startup, VT_EMPTY, VTS_NONE) DISP_FUNCTION(CEventSink, "Quit", Quit, VT_EMPTY, VTS_NONE) DISP_FUNCTION(CEventSink, "DocumentChange", DocumentChange, VT_EMPTY, VTS_NONE) END_DISPATCH_MAP() static const GUID IID_ICEventSink = {0x000209f7,0x000,0x0000,{0xc0,0x00,0x0,0x00,0x00,0x00,0x00,0x46 } }; BEGIN_INTERFACE_MAP(CEventSink, CCmdTarget) INTERFACE_PART(CEventSink, IID_ICEventSink, Dispatch) END_INTERFACE_MAP() PB als Add-On Tipps & Tricks 2
void CEventSink::Startup() { //We'll never get this one, it happens before we capture the events #ifdef _DEBUG MessageBox( NULL, "Startup", "Message", MB_ICONEXCLAMATION | MB_OK ); #endif pbclass clz = m_userdata->session->GetClass(m_userdata->object); pbmethodID mid = m_userdata->session->GetMethodID(clz, "startup", PBRT_EVENT, "LUL" ); PBCallInfo ci; m_userdata->session->InitCallInfo(clz, mid, &ci); m_userdata->session->TriggerEvent(m_userdata->object, mid, &ci); m_userdata->session->FreeCallInfo(&ci); } PB als Add-On Tipps & Tricks 2
void CEventSink::Quit() { #ifdef _DEBUG MessageBox( NULL, "Quit", "Message", MB_ICONEXCLAMATION | MB_OK ); #endif pbclass clz = m_userdata->session->GetClass(m_userdata->object); pbmethodID mid = m_userdata->session->GetMethodID(clz, "quit", PBRT_EVENT, "LUL" ); PBCallInfo ci; m_userdata->session->InitCallInfo(clz, mid, &ci); m_userdata->session->TriggerEvent(m_userdata->object, mid, &ci); m_userdata->session->FreeCallInfo(&ci); } PB als Add-On Tipps & Tricks 2
void CEventSink::DocumentChange() { #ifdef _DEBUG MessageBox( NULL, "DocumentChange", "Message", MB_ICONEXCLAMATION | MB_OK ); #endif pbclass clz = m_userdata->session->GetClass(m_userdata->object); pbmethodID mid = m_userdata->session->GetMethodID(clz, "documentchange", PBRT_EVENT, "LUL" ); PBCallInfo ci; m_userdata->session->InitCallInfo(clz, mid, &ci); m_userdata->session->TriggerEvent(m_userdata->object, mid, &ci); m_userdata->session->FreeCallInfo(&ci); } PB als Add-On Tipps & Tricks 2
Erzeugen der PBD erase pbnioleobject.pbx copy release\pbnioleobject.dll pbnioleobject.pbx "D:\Programme\Sybase\PowerBuilder 10.5\SDK\PBNI\pbx2pbd105.exe" pbnioleobject.pbd pbnioleobject.pbx pause PB als Add-On Tipps & Tricks 2
Verbindung herstellen Integer li_rc SetPointer ( HourGlass! ) try inv_word = CREATE n_cpp_oleobject_word_application IF IsNull ( inv_word ) THEN Return li_rc = inv_word.ConnectToNewObject ( "Word.Application.8" ) IF li_rc <> 0 THEN Return li_rc inv_word.Visible = TRUE li_rc = inv_word.CaptureEvents() catch (Throwable MyError ) Return -1 end try CHOOSE CASE li_rc CASE 1 Return 1 CASE ELSE Return li_rc END CHOOSE PB als Add-On Tipps & Tricks 2
PB als Add-On Tipps & Tricks 2
PB als Add-On Tipps & Tricks 2
PB als Add-On Tipps & Tricks 2
Möglichkeiten der SBO- UI-API: • Reaktion auf SBO-Events • Erzeugen von SBO-Objekten, wie z.B. Form, Menü, Button, Datenfelder • Problem: • Keine Verwendung von PB-Objekte möglich • Somit auch keine Datawindows, bzw. PSRs PB als Add-On Tipps & Tricks 2
Lösung: • Erzeugen einer SBO-Form • Erzeugen eines Childwindow in PB • Ermittlung der Handle beider Fenster • PB-Child als Child der SBO-Form setzen PB als Add-On Tipps & Tricks 2
// Zunächst eine Form in SAP öffnen ls_uid = 'beas_' + string(now(),"hhmmssffff") ls_title = aw_window.title li_top = UnitsToPixels(aw_window.y, YUnitsToPixels! ) li_left = UnitsToPixels(aw_window.x, XUnitsToPixels! ) li_width = UnitsToPixels(aw_window.width, XUnitsToPixels! ) li_height = UnitsToPixels(aw_window.height, YUnitsToPixels! ) ll_rc = this.of_sboform_add( ls_uid, "", this.ft_sizable, this.fbs_sizable, "", lole_form, ls_title, li_left, li_width, li_top, li_height ) if not isvalid(lole_form) then return FAILURE // Dann das Handle das SBO Fensters holen (Klasse: TMMDIChildClass) SetNull( ls_WindowName ) setnull( ll_hStartingChild ) ll_hFrameWindow = FindWindowA( SBOFRAME_CLASS, ls_WindowName) // erst den Frame … ll_hClientWindow = FindWindowExA( ll_hFrameWindow, ll_hStartingChild, SBOCLIENT_CLASS, ls_WindowName) // dann den Client … ll_hChildWindow = FindWindowExA( ll_hClientWindow, ll_hStartingChild, SBOCHILD_CLASS, ls_WindowName) // und dann das Child … // Fenster positionieren aw_window.x = 0 // ganz nach links aw_window.y = 0 // ganz nach oben // Das Handle des Childs bilden ll_hPBWindow = handle(aw_window) if isnull(ll_hPBWindow) then return FAILURE // das Handle des SBO-Parents an das PB-Child übergeben ll_hParentWindow = ll_hChildWindow ll_rc = SetParent( ll_hPBWindow, ll_hParentWindow) PB als Add-On Tipps & Tricks 2
Sind noch Fragen offen? Bei Rückfragen oder Anregungen bitte an: Ludwin Feiten Power People Inh. Ludwin Feiten Am Borsigturm 50 D-13507 Berlin fon +49 (0)30 43032350 fax +49 (0)30 43032355 http://www.powerpeople.de mailto:ludwin.feiten@powerpeople.de Kontakt Tipps & Tricks 2