christoph menken „gesammelte werke“ powerbuilder tipps und tricks und sonstiges aus der...
TRANSCRIPT
Christoph Menken
„Gesammelte Werke“PowerBuilder Tipps und Tricks und
sonstiges aus der „normalen“ Client-Server Entwicklung
Ludwin Feiten, Christoph MenkenPower People
Teil 2
PBUGGFrankfurt 21.05.2007
Tipps & Tricks 2Folie 2/36
Christoph Menken
Fahrplan
• Tipps & Tricks im Web• .net Komponente via
ComWrapper• Powerbuilder in SAP
Business One
PBUGGFrankfurt 21.05.2007
Tipps & Tricks 2Folie 3/36
Christoph Menken
Tipps & Tricks im Web (Auszug)
• 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
PBUGGFrankfurt 21.05.2007
Tipps & Tricks 2Folie 4/36
Christoph Menken
.net Komponente via ComWrapper
• Neue Klassenbibliothek (Class Library) erzeugen
PBUGGFrankfurt 21.05.2007
Tipps & Tricks 2Folie 5/36
Christoph Menken
.net Komponente via ComWrapper
• Klasse und alle zugehörigen Referenzen umbenennen
PBUGGFrankfurt 21.05.2007
Tipps & Tricks 2Folie 6/36
Christoph Menken
.net Komponente via ComWrapper
PBUGGFrankfurt 21.05.2007
Tipps & Tricks 2Folie 7/36
Christoph Menken
.net Komponente via ComWrapper
PBUGGFrankfurt 21.05.2007
Tipps & Tricks 2Folie 8/36
Christoph Menken
.net Komponente via ComWrapper
PBUGGFrankfurt 21.05.2007
Tipps & Tricks 2Folie 9/36
Christoph Menken
.net Komponente via ComWrapper
PBUGGFrankfurt 21.05.2007
Tipps & Tricks 2Folie 10/36
Christoph Menken
.net Komponente via ComWrapper
set dnf=C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727set sdk=D:\Programme\Microsoft Visual Studio 8\SDK\v2.0\
Bin
%dnf%\regasm $(TargetFileName) /regfile:$(TargetName).reg
%sdk%\gacutil /i "$(TargetPath)"
PBUGGFrankfurt 21.05.2007
Tipps & Tricks 2Folie 11/36
Christoph Menken
.net Komponente via ComWrapper
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;
PBUGGFrankfurt 21.05.2007
Tipps & Tricks 2Folie 12/36
Christoph Menken
.net Komponente via ComWrapper
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);
}
}}
PBUGGFrankfurt 21.05.2007
Tipps & Tricks 2Folie 13/36
Christoph Menken
.net Komponente via ComWrapper
• DLL erstellen• Registryeintrag hinzufügenREGEDIT4
[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}]
PBUGGFrankfurt 21.05.2007
Tipps & Tricks 2Folie 14/36
Christoph Menken
.net Komponente via ComWrapper
• Testprogramm in C# erstellen
PBUGGFrankfurt 21.05.2007
Tipps & Tricks 2Folie 15/36
Christoph Menken
.net Komponente via ComWrapper
• Die DotNetSMTP.dll als Referenz hinzufügen
PBUGGFrankfurt 21.05.2007
Tipps & Tricks 2Folie 16/36
Christoph Menken
.net Komponente via ComWrapper
• Einen Button hinzufügen• Im clicked-Event folgenden Code hinzufügen:
DotNetSMTP.DotNetSMTP smtpclient = new DotNetSMTP.DotNetSMTP();
smtpclient.SenderName = "Christoph Menken";
smtpclient.SenderEmail = "[email protected]";
smtpclient.SmtpServer = "smtp.gmx.de";
smtpclient.RecipientEmail = "[email protected]";
smtpclient.MessageText = "This is a test, this is only a test.";
smtpclient.Subject = "Dot Net via COM is cool";
smtpclient.sendMail();
PBUGGFrankfurt 21.05.2007
Tipps & Tricks 2Folie 17/36
Christoph Menken
.net Komponente via ComWrapper
• Im Powerbuilder:integer li_rc
oleobject lole_smtp
lole_smtp = CREATE oleobjectli_rc = lole_smtp.ConnectToNewObject ( "DotNetSMTP.DotNetSMTP" )if li_rc = 0 then
lole_smtp.SenderName = "Christoph Menken"lole_smtp.SenderEmail = "[email protected]"lole_smtp.RecipientEmail = "[email protected]"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"
elseMessageBox( parent.title, &
"Error calling DotNetSMTP via COM: " + string(li_rc) )end if
PBUGGFrankfurt 21.05.2007
Tipps & Tricks 2Folie 18/36
Christoph Menken
PB als Add-On
• 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
PBUGGFrankfurt 21.05.2007
Tipps & Tricks 2Folie 19/36
Christoph Menken
PB als Add-On
• 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“
PBUGGFrankfurt 21.05.2007
Tipps & Tricks 2Folie 20/36
Christoph Menken
PB als Add-On
• Lösung: PBNIErstellen eines PBNI COM-Objekt, welches das SBO-UI-COM-Objekt verwendet und die Events in PB zur Verfügung stellt
SAP Business One
PB
SBO UI API
PBNI-COM-Objekt
RegistrierungTriggert Events
PBUGGFrankfurt 21.05.2007
Tipps & Tricks 2Folie 21/36
Christoph Menken
PB als Add-On
• Beispiel: PBNIOLEObject– Einfaches exemplarisches
Beispiel – Integration eines PB-
Programms in MS Word– von Bruce Armstrong
PBUGGFrankfurt 21.05.2007
Tipps & Tricks 2Folie 22/36
Christoph Menken
PB als Add-On
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 ;
}
PBUGGFrankfurt 21.05.2007
Tipps & Tricks 2Folie 23/36
Christoph Menken
PB als Add-On
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 ;
}
PBUGGFrankfurt 21.05.2007
Tipps & Tricks 2Folie 24/36
Christoph Menken
PB als Add-On
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()
PBUGGFrankfurt 21.05.2007
Tipps & Tricks 2Folie 25/36
Christoph Menken
PB als Add-On
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);
}
PBUGGFrankfurt 21.05.2007
Tipps & Tricks 2Folie 26/36
Christoph Menken
PB als Add-On
void CEventSink::Quit() {
#ifdef _DEBUGMessageBox( 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);
}
PBUGGFrankfurt 21.05.2007
Tipps & Tricks 2Folie 27/36
Christoph Menken
PB als Add-On
void CEventSink::DocumentChange() {
#ifdef _DEBUGMessageBox( 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);
}
PBUGGFrankfurt 21.05.2007
Tipps & Tricks 2Folie 28/36
Christoph Menken
PB als Add-On
Erzeugen der PBDerase pbnioleobject.pbxcopy release\pbnioleobject.dll
pbnioleobject.pbx"D:\Programme\Sybase\
PowerBuilder 10.5\SDK\PBNI\pbx2pbd105.exe" pbnioleobject.pbd pbnioleobject.pbx
pause
PBUGGFrankfurt 21.05.2007
Tipps & Tricks 2Folie 29/36
Christoph Menken
PB als Add-On
Verbindung herstellenInteger li_rc
SetPointer ( HourGlass! )
tryinv_word = CREATE n_cpp_oleobject_word_applicationIF IsNull ( inv_word ) THEN Returnli_rc = inv_word.ConnectToNewObject ( "Word.Application.8" )IF li_rc <> 0 THEN Return li_rcinv_word.Visible = TRUEli_rc = inv_word.CaptureEvents()
catch (Throwable MyError )Return -1
end try
CHOOSE CASE li_rcCASE 1
Return 1CASE ELSE
Return li_rcEND CHOOSE
PBUGGFrankfurt 21.05.2007
Tipps & Tricks 2Folie 30/36
Christoph Menken
PB als Add-On
PBUGGFrankfurt 21.05.2007
Tipps & Tricks 2Folie 31/36
Christoph Menken
PB als Add-On
PBUGGFrankfurt 21.05.2007
Tipps & Tricks 2Folie 32/36
Christoph Menken
PB als Add-On
PBUGGFrankfurt 21.05.2007
Tipps & Tricks 2Folie 33/36
Christoph Menken
PB als Add-On
• 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
PBUGGFrankfurt 21.05.2007
Tipps & Tricks 2Folie 34/36
Christoph Menken
PB als Add-On
• Lösung:– Erzeugen einer SBO-Form– Erzeugen eines
Childwindow in PB– Ermittlung der Handle
beider Fenster– PB-Child als Child der SBO-
Form setzen
PBUGGFrankfurt 21.05.2007
Tipps & Tricks 2Folie 35/36
Christoph Menken
PB als Add-On
// Zunächst eine Form in SAP öffnenls_uid = 'beas_' + string(now(),"hhmmssffff")ls_title = aw_window.titleli_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 positionierenaw_window.x = 0 // ganz nach linksaw_window.y = 0 // ganz nach oben
// Das Handle des Childs bildenll_hPBWindow = handle(aw_window)if isnull(ll_hPBWindow) then return FAILURE
// das Handle des SBO-Parents an das PB-Child übergebenll_hParentWindow = ll_hChildWindowll_rc = SetParent( ll_hPBWindow, ll_hParentWindow)
PBUGGFrankfurt 21.05.2007
Tipps & Tricks 2Folie 36/36
Christoph Menken
Kontakt
Sind noch Fragen offen?
Bei Rückfragen oder Anregungen bitte an:
Ludwin Feiten
Power PeopleInh. Ludwin FeitenAm Borsigturm 50
D-13507 Berlin
fon +49 (0)30 43032350fax +49 (0)30 43032355
http://www.powerpeople.demailto:[email protected]