October 29, 2025, 02:25:40 AM

News:

IonicWind Snippit Manager 2.xx Released!  Install it on a memory stick and take it with you!  With or without IWBasic!


Mini DDE example

Started by sapero, January 18, 2009, 03:28:32 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

sapero

January 18, 2009, 03:28:32 PM Last Edit: January 19, 2009, 06:37:10 AM by sapero
When you want the Windows Explorer to open document files in your application you have no problem when your application is not already open. Explorer opens your app and passes the document file as parameter, but when your app is already open Explorer would open a new instance of your app! e.g.. in a MDI Application you want the file to open in only one instance.

EDIT: bugfix in CRegKey::SetValue.
$include "windowssdk.inc"
$include "shlwapi.inc"
autodefine "OFF"

ENUM controls
IDC_LOG = 1000
IDC_REGISTER
IDC_UNREGISTER
ENDENUM

$define SZ_DDE_COMMAND     "[Open(\"%1\")]"
$define SZ_DDE_TOPIC       "system"
$define SZ_DDE_APPLICATION "EbasicDdeDemo"
' helpers to split SZ_DDE_COMMAND
$define SZ_DDE_COMPARE1    "[Open(\""
$define SZ_DDE_COMPARE2    "\")]"

DIALOG d1
CREATEDIALOG d1,0,0,477,240,0x80CA0080,0,"Mini DDE example",&d1_handler
CONTROL d1,@LISTBOX,"",12,10,452,173,0x50A10140,IDC_LOG
CONTROL d1,@SYSBUTTON,"Register",19,198,77,26,0x50010000,IDC_REGISTER
CONTROL d1,@SYSBUTTON,"Unregister",101,198,77,26,0x50010000,IDC_UNREGISTER
DOMODAL d1

class CRegKey
declare CRegKey()
declare _CRegKey()
declare Attach(HKEY hkChild)
declare Close()
declare OpenDirect(HKEY key, LPSTR szSubkey, REGSAM samDesired),BOOL
declare CreateDirect(HKEY key, LPSTR szSubkey, REGSAM samDesired, opt pointer pdwDisposition=0),BOOL
declare Open(LPSTR szSubkey, REGSAM samDesired, CRegKey result),BOOL
declare CreateSubkey(LPSTR szSubkey, REGSAM samDesired, CRegKey result, opt pointer pdwDisposition=0),BOOL
declare GetValue(LPSTR pszName, LPSTR pszBuffer, pointer pType, pointer pCch),LONG
declare SetValue(LPSTR pszName, LPSTR pszBuffer, DWORD dwType, DWORD cch),LONG
declare DeleteValue(LPSTR pszName),LONG
declare DeleteSubkey(LPSTR pszName),LONG
HKEY m_hKey
endclass


SUB d1_handler
SELECT @MESSAGE
CASE @IDINITDIALOG
CENTERWINDOW d1
AddString(d1, IDC_LOG, "Right click on EBA file, select Open With and select this program")

CASE @IDCLOSEWINDOW
CLOSEDIALOG d1,@IDOK

CASE WM_DDE_ACK
AddString(d1, IDC_LOG, "Received WM_DDE_ACK")
CASE WM_DDE_ADVISE
AddString(d1, IDC_LOG, "Received WM_DDE_ADVISE")
CASE WM_DDE_DATA
AddString(d1, IDC_LOG, "Received WM_DDE_DATA")
CASE WM_DDE_POKE
AddString(d1, IDC_LOG, "Received WM_DDE_POKE")
CASE WM_DDE_REQUEST
AddString(d1, IDC_LOG, "Received WM_DDE_REQUEST")
CASE WM_DDE_UNADVISE
AddString(d1, IDC_LOG, "Received WM_DDE_UNADVISE")

CASE WM_DDE_INITIATE
AddString(d1, IDC_LOG, "Received WM_DDE_INITIATE")
OnDdeInitialize(@WPARAM, @LPARAM&0xFFFF, @LPARAM>>16)

CASE WM_DDE_EXECUTE
AddString(d1, IDC_LOG, "Received WM_DDE_EXECUTE")
OnDdeExecute(@WPARAM, @LPARAM)

CASE WM_DDE_TERMINATE
AddString(d1, IDC_LOG, "Received WM_DDE_TERMINATE")
OnDdeTerminate(@WPARAM)

CASE @IDCONTROL
SELECT @WPARAM

/* respond to control notifications here */
CASE IDC_REGISTER
Register()

CASE IDC_UNREGISTER
Unregister()

ENDSELECT
ENDSELECT
RETURN
ENDSUB



sub OnDdeInitialize(HWND hwndClient, ATOM atomApplication, ATOM atomTopic)
' To complete the initiation of a conversation, the server application must respond
' with one or more WM_DDE_ACK messages, where each message is for a separate topic
ATOM aApp = GlobalAddAtom(SZ_DDE_APPLICATION)
ATOM aTop = GlobalAddAtom(SZ_DDE_TOPIC)

if ((atomApplication = aApp) and (atomTopic = aTop))

AddString(d1, IDC_LOG, "   Sending WM_DDE_ACK")
SendMessage(hwndClient, WM_DDE_ACK, d1.hwnd, MAKELPARAM(aApp, aTop))

endif

GlobalDeleteAtom(aApp)
GlobalDeleteAtom(aTop)
return
endsub


sub OnDdeExecute(HWND hwndClient, HGLOBAL hgl)
' The server application posts the WM_DDE_ACK message to respond positively or negatively.
istring szPath[MAX_PATH]
USHORT code = 0x0000 ' DDEACK structure
if (hgl)

pointer text = GlobalLock(hgl)
if (text)

AddString(d1, IDC_LOG, using("   HGLOBAL: &", *<STRING>text))

if (strnicmp(text, SZ_DDE_COMPARE1, strlen(SZ_DDE_COMPARE1)) = 0)

pointer path = text + 7
pointer pEnd = strstr(path, SZ_DDE_COMPARE2)

if (pEnd)

int cch = pEnd - path
if (cch < MAX_PATH)

MoveMemory(szPath, path, cch)
szPath[cch] = 0

' use szPath to open the file
AddString(d1, IDC_LOG, using("   Extracted: &", szPath))

code = 0x8000
if (IsIconic(d1.hwnd))
ShowWindow(d1, @SWRESTORE)
endif

SetFocus(d1)

endif
endif
endif
GlobalUnlock(text)
endif
endif
AddString(d1, IDC_LOG, "   Sending WM_DDE_ACK")
PostMessage(hwndClient, WM_DDE_ACK, d1.hwnd, PackDDElParam(WM_DDE_ACK, code, hgl))
return
endsub


sub OnDdeTerminate(HWND hwndClient)
' The server application should respond by posting a WM_DDE_TERMINATE message
AddString(d1, IDC_LOG, "   Sending WM_DDE_TERMINATE")
PostMessage(hwndClient, WM_DDE_TERMINATE, d1.hwnd, 0)
return
endsub


' the code below is to register/unregister DDE in the registry

sub Register()
istring szPath[MAX_PATH + 8]
istring szName[MAX_PATH]

GetModuleFileName(0, szPath, MAX_PATH)
LPSTR pName = PathFindFileName(szPath)
szName = *<STRING>pName

/* [HKEY_CURRENT_USER\Software\Classes\Applications\DdeDemo.exe\shell]
// [open]
//      [command]
//              @ = D:\EBDev\forum\DdeDemo.exe "%1"
//      [ddeexec]
//              @ = [Open("%1")]
//              [application]
//                          @ = DdeDemo.exe
//              [topic]
//                          @ = system
//
// [HKEY_CURRENT_USER\Software\Classes\.eba\OpenWithList\DdeDemo.exe]
*/

CRegKey Applications
CRegKey Application
CRegKey open
CRegKey command
CRegKey ddeexec
CRegKey ddeChild
CRegKey OpenWithList

if (Applications.CreateDirect(HKEY_CURRENT_USER, "Software\\Classes\\Applications", KEY_CREATE_SUB_KEY))

if (Applications.CreateSubkey(szName, KEY_CREATE_SUB_KEY, Application))

PathQuoteSpaces(szPath)
szPath += " \"%1\""

if (Application.CreateSubkey("shell\\open", KEY_CREATE_SUB_KEY, open))

if (open.CreateSubkey("command", KEY_WRITE, command))

command.SetValue(NULL, szPath, REG_SZ, strlen(szPath)+1)

if (OpenWithList.CreateDirect(HKEY_CURRENT_USER, "Software\\Classes\\.eba\\OpenWithList", KEY_CREATE_SUB_KEY))
OpenWithList.CreateSubkey(szName, KEY_CREATE_SUB_KEY, Application)
endif

if (open.CreateSubkey("ddeexec", KEY_WRITE, ddeexec))
ddeexec.SetValue(NULL, SZ_DDE_COMMAND, REG_SZ, strlen(SZ_DDE_COMMAND)+1)

if (ddeexec.CreateSubkey("application", KEY_WRITE, ddeChild))
ddeChild.SetValue(NULL, SZ_DDE_APPLICATION, REG_SZ, strlen(SZ_DDE_APPLICATION)+1)
endif
if (ddeexec.CreateSubkey("topic", KEY_WRITE, ddeChild))
ddeChild.SetValue(NULL, SZ_DDE_TOPIC, REG_SZ, strlen(SZ_DDE_TOPIC)+1)
endif
endif
endif
endif
endif
endif

return
endsub


sub Unregister()
istring szPath[MAX_PATH + 8]

CRegKey Applications
CRegKey child
CRegKey Classes
CRegKey OpenWithList

GetModuleFileName(0, szPath, MAX_PATH)
LPSTR pName = PathFindFileName(szPath)

if (Applications.OpenDirect(HKEY_CURRENT_USER, "Software\\Classes\\Applications", KEY_WRITE))
SHDeleteKey(Applications.m_hkey, pName)
endif

if (Classes.OpenDirect(HKEY_CURRENT_USER, "Software\\Classes", KEY_WRITE))
if (Classes.Open(".eba", KEY_WRITE, child))
if (child.Open("OpenWithList", KEY_WRITE, OpenWithList))
' delete Software\Classes\.eba\OpenWithList\DdeDemo.exe
OpenWithList.DeleteSubkey(pName)
' if Software\Classes\.eba\OpenWithList is empty, delete it
SHDeleteEmptyKey(child.m_hkey, "OpenWithList")
endif
' if Software\Classes\.eba is empty, delete it
SHDeleteEmptyKey(Classes.m_hkey, ".eba")
endif
endif

return
endsub




sub CRegKey::CRegKey()
m_hKey = 0
return
endsub


sub CRegKey::_CRegKey()
Close()
return
endsub


sub CRegKey::Attach(HKEY hkChild)
Close()
m_hKey = hkChild
return
endsub


sub CRegKey::Close()
if (m_hKey) then RegCloseKey(m_hKey)
m_hKey = 0
return
endsub


sub CRegKey::Open(LPSTR szSubkey, REGSAM samDesired, CRegKey result),BOOL
return result.OpenDirect(m_hkey, szSubkey, samDesired)
endsub


sub CRegKey::CreateSubkey(LPSTR szSubkey, REGSAM samDesired, CRegKey result, pointer pdwDisposition),BOOL
return result.CreateDirect(m_hkey, szSubkey, samDesired, pdwDisposition)
endsub


sub CRegKey::OpenDirect(HKEY key, LPSTR szSubkey, REGSAM samDesired),BOOL
BOOL success = FALSE

HKEY hk
if (RegOpenKeyEx(key, szSubkey, 0, samDesired, &hk) = 0)
success = TRUE
Attach(hk)
endif

return success
endsub


sub CRegKey::CreateDirect(HKEY key, LPSTR szSubkey, REGSAM samDesired, pointer pdwDisposition),BOOL
BOOL success = FALSE

HKEY hk
if (RegCreateKeyEx(key, szSubkey, 0, 0, 0, samDesired, 0, &hk, pdwDisposition) = 0)
success = TRUE
Attach(hk)
endif

return success
endsub


sub CRegKey::GetValue(LPSTR pszName, LPSTR pszBuffer, pointer pType, pointer pCch),LONG
return RegQueryValueEx(m_hKey, pszName, 0, pType, pszBuffer, pCch)
endsub


sub CRegKey::SetValue(LPSTR pszName, LPSTR pszBuffer, DWORD dwType, DWORD cch),LONG
return RegSetValueEx(m_hKey, pszName, 0, dwType, pszBuffer, cch)
endsub


sub CRegKey::DeleteValue(LPSTR pszName),LONG
return RegDeleteValue(m_hKey, pszName)
endsub


sub CRegKey::DeleteSubkey(LPSTR pszName),LONG
return RegDeleteKey(m_hKey, pszName)
endsub