Here's my code in the u_dw Other() event:
CHOOSE CASE message.number
CASE WM_MOUSEWHEEL
// v1 and v2, mjl, 13/04/20: Since win8 and w10 totally ignore the mouse settings when working remotely, I've re-introduced the code to scroll:
// First check the user isn't "zooming" by using CTRL+mouseWheel:
IF KeyDown( keyControl!) then
RETURN 0
END IF
// v1 and v2, mjl, 19/05/20: shouldn't scroll when there's only one row:
if this.rowcount() = 1 then
message.processed = true // has to be the last command before doing the RETURN 0
RETURN 0
end if
CONSTANT uint SPI_GETWHEELSCROLLLINES = 104
CONSTANT Long WM_VSCROLL = 277
CONSTANT Long SB_LINEDOWN = 1
CONSTANT Long SB_LINEUP = 0
int li_WheelMouseLine, li_index
int li_lines
// Function boolean SystemParametersInfoW(uint wActon, uint wParam, REF int pvParam, uint fUpdateProfile) Library "USER32.DLL"
SystemParametersInfoW(SPI_GETWHEELSCROLLLINES, 0, ref li_WheelMouseLine, 0)
li_lines = IntHigh(wParam) / 120
this.SetRedraw(false)
IF li_lines > 0 THEN
FOR li_index = 1 TO li_WheelMouseLine
Send(Handle(THIS), WM_VSCROLL, SB_LINEUP,0)
NEXT
ELSE
FOR li_index = 1 TO li_WheelMouseLine
Send(Handle(THIS), WM_VSCROLL, SB_LINEDOWN,0)
NEXT
END IF
this.SetRedraw(true) // has to be before setting message.processed = true, if not it makes the message.processed = true to NOT work
message.processed = true // has to be the last command before doing the RETURN 0
RETURN 0
END CHOOSE
CHOOSE CASE wparam
CASE WM_OUTLOOK_DROP // email dropped from Outlook?
// ib_nOther is being set in key event:
if ib_noOther then
post setpointer(arrow!)
message.processed = true
return 0
end if
if not ib_allowDropFromExplorer then
return 0
end if
// avoid reminders to popup during this process:
// we will assign is_openWindow only if it's not already being set by some other window, or this same window previously:
boolean lb_reset
if gnv_app.is_open_responseWindow = "" then
lb_reset = true
gnv_app.is_open_responsewindow = this.classname()
end if
// if this is the first file dropped, we get a count of selected emails in Outlook (and set the application to front)
if iul_dropped_files = 0 then
// it's the first file being dropped:
// bring the application to front
n_funcs lnv
lnv.POST of_application_to_front()
// use ole to determine the number of selected files:
try
oleobject lole_outlook_app
lole_outlook_app = create oleobject
setpointer(hourglass!)
If lole_outlook_app.ConnectToNewObject("Outlook.Application") <> 0 Then
gnv_app.inv_error.of_Message( "cannot_log_onto_mail" )
gnv_app.of_debug("Outlook: cannot connect to outlook.application - constructor")
if lb_reset then
gnv_app.is_open_responseWindow = ""
end if
return 0 // v2, mjl, 07/07/20: instead of return without a value
End If
il_selected_outlook_count = lole_outlook_app.ActiveExplorer.Selection.Count
string ls_dir, ls_renamedDir
if gnv_app.ii_officeBitness = 64 then
// v3, mjl, 25/05/21: due to office 64 bit issues we now use OLE to get the selected emails:
// store all of the dropped / selected files:
oleobject lole_item, lole_saveAs, lole_nameSpace
//string ls_body, ls_msg, ls_from, ls_to, ls_cc, ls_bcc, ls_name
string ls_subject, ls_fName, ls_entryID, is_empty[]
int li_rc
ulong ll_i
this.is_dropped_fileGUIDS = is_empty
FOR ll_i = 1 to il_selected_outlook_count
lole_item = lole_outlook_app.ActiveExplorer.Selection.item(ll_i)
li_rc = lole_item.class
// datetime ldtdate
CHOOSE CASE li_rc
// CASE 26 //appointment
// ls_body = lole_item.body
// ls_msg += '~r~n Appointment No: ' + string(ll_i) + ' of ' + string(il_selected_outlook_count) + '~r~n' + ls_body
// // lots of other stuff could be here
// CASE 40 // contact
// ls_body = lole_item.body
// ls_msg += '~r~n Contact No: ' + string(ll_i) + ' of ' + string(il_selected_outlook_count) + '~r~n' + ls_body
CASE 43 // mail
is_dropped_fileGUIDS[ll_i] = lole_item.EntryID
// we will only reset if is_openWindow was not already some other window
if lb_reset then
gnv_app.is_open_responseWindow = ""
end if
// CASE 48 // task
// ls_subject = lole_item.subject
// ls_to = lole_item.owner
// ls_body = lole_item.body
// ls_msg = '~r~nSubject: ' + ls_subject + '~r~nOwner: ' + ls_to + '~r~nBody: ' + ls_body
// ls_msg += '~r~n Task No: ' + string(ll_i) + ' of ' + string(il_selected_outlook_count) + '~r~n' + ls_msg
END CHOOSE
if isvalid(lole_item) then
DESTROY lole_item
end if
NEXT
end if
catch ( runtimeError runtErro)
// do nothing
if isvalid(lole_outlook_app) then
lole_outlook_app.disconnectobject( )
destroy lole_outlook_app
if lb_reset then
gnv_app.is_open_responseWindow = ""
end if
return 0
end if
finally
if isvalid(lole_outlook_app) then
lole_outlook_app.disconnectobject()
destroy lole_outlook_app
end if
end try
end if
if gnv_app.ii_officeBitness = 32 then
// Called when email Messages are dropped
string ls_Message, ls_Files, ls_Header
string ls_Pre, ls_fileName
s_finddata lstr_FindData
integer li_Pos
long ll_Handle
setpointer(hourglass!)
ls_Message = String( lparam, "address" )
li_Pos = Pos( ls_Message, "~r~n" )
IF li_Pos > 0 THEN
//ls_Header = Mid( ls_Message, li_Pos + 2 )
ls_Message = Left( ls_Message, li_Pos - 1 )
//ls_Header = "~r~nHeader:~r~n" + ls_Header
END IF
ls_Pre = Left( ls_Message, LastPos( ls_Message, "." ) - 1)
ls_Dir = Left( ls_Message, LastPos( ls_Message, "\" ) - 1)
// Check whether there are attachments available
ll_Handle = inv_platform.FindFirstFile(ls_Pre + "*.*", lstr_FindData)
If ll_Handle < 1 Then
if lb_reset then
gnv_app.is_open_responseWindow = ""
end if
message.processed = true
Return 0
end if
end if
iul_dropped_files ++
if gnv_app.ii_officeBitness = 32 then
Do
//ls_Files = ls_Files + "~r~n" + lstr_FindData.ch_filename
ls_fileName = lstr_FindData.ch_filename
if lower(right(ls_fileName, 4)) = ".msg" then
exit
end if
Loop Until Not inv_platform.FindNextFile(ll_Handle, lstr_FindData)
inv_platform.FindClose(ll_Handle)
ls_renamedDir = ls_dir + "-"+ string(iul_dropped_files)
// we might have to shorten the filename before renaming the folder
if len(ls_renamedDir + "\" + ls_filename) > 255 then
int li_chopOff
string ls_newFileName
li_chopOff = len(ls_renamedDir + "\" + ls_filename) - 255 + 4 // plus 4 to cut off ".msg"
ls_newFileName = mid(ls_fileName, 1, len(ls_fileName) - li_chopOff) + ".msg"
if fileMove(ls_dir + "\" + ls_fileName, ls_dir + "\" + ls_newFileName) <> 1 then
if lb_reset then
gnv_app.is_open_responseWindow = ""
end if
message.processed = true
return -1
end if
ls_fileName = ls_newFileName
end if
// rename the folder:
if filemove(ls_dir, ls_renamedDir) <> 1 then
if lb_reset then
gnv_app.is_open_responseWindow = ""
end if
message.processed = true
return 0
end if
is_dropped_fileNames[iul_dropped_files] = ls_renamedDir + "\" + ls_fileName
end if
// we will only reset if is_openWindow was not already some other window
if lb_reset then
gnv_app.is_open_responseWindow = ""
end if
if gnv_app.ii_officeBitness = 32 then
// the folder will be deleted in ue_postdropOutlookFiles
is_delete_directories[iul_dropped_files] = ls_renamedDir
end if
if iul_dropped_files = il_selected_outlook_count then
// this was the last file selected in outlook
this.event post ue_dropoutlookfiles( )
end if
setpointer(hourglass!)
// post MessageBox( "Message dropped" , "Files located in " + ls_Dir + "~r~nFiles:" + ls_Files + ls_Header)
RETURN 0
END CHOOSE
RETURN 0
Some things are not relevant to the current problem. Have a look at "ii_officeBitness". If you need more information you can contact me on LinkedIn (Miguel Leeuwe).
This code is just to give you an idea. "is_dropped_fileGUIDS" has been filled in the Other() event of the dw.
I have a nvo to deal with the dropped files which has a function "of_dropped_outlookFiles()":
// adw
// as_notetype
// as_customer
long ll_i, ll_max
boolean lb_reset
n_filesys ln_fsys
int li_file_len
// avoid reminders to popup during this process:
// we will assign is_openWindow only if it's not already being set by some other window, or this same window previously:
if gnv_app.is_open_responseWindow = "" then
gnv_app.is_open_responseWindow = this.classname()
lb_reset = true
end if
// only filled when gnv_app.ii_officeBitness = 64:
if Upperbound(adw.is_dropped_fileGUIDS) > 0 then
// -------------------------------------------------------------------------------------------------------------------------------
// dropping process has finished, we can now first delete all the drop.msg files that were saved by the dllddll.dll when on 64 bit:
// -------------------------------------------------------------------------------------------------------------------------------
// get the list of files and directories from the %temp% windows folder:
string ls_name[], ls_archDir, ls_tempDir, ls_path, ls_fullname, ls_fileName, ls_filetype
DateTime ldt_write[], ldt_modified
Boolean lb_subdir[]
Double ld_size[]
long ll_filesize, ll_cnt, ll_sortType
ls_tempDir = gnv_app.is_win_temp_dir
ll_max = ln_fsys.of_getfiles(ls_tempDir, False, ls_name, ld_size, ldt_write, lb_subdir)
If ll_max = -1 Then
MessageBox("Error", "There is no disk in drive " + ls_tempDir, Exclamation!)
Else
For ll_cnt = 1 To ll_max
If lb_subdir[ll_cnt] Then
// it's a directory and what we are looking for:
ll_sorttype = 0
ll_filesize = 0
ls_fullname = ls_tempDir + ls_name[ll_cnt]
// check if it's a today's folder:
if not left(ls_name[ll_cnt], 8) = string(today(), 'yyyymmdd') then
continue
end if
// check if the folder contains a single file named "drop.msg", if so delete:
string ls_name2[]
boolean lb_subdir2[]
DateTime ldt_write2[]
Double ld_size2[]
if ln_fsys.of_getfiles(ls_fullname, False, ls_name2, ld_size2, ldt_write2, lb_subdir2) = 1 then
if not lb_subdir2[1] then
// check if there's a single file called "drop.msg" in it:
if not lower(ls_name2[1]) = "drop.msg" then
continue
end if
// delete the folder and anything in it:
if ln_fSys.of_delete_directory( ls_fullname ) = -1 then
Messagebox("Error deleting temp folder", "Failed to delete the folder " + ls_fullname)
return -1
end if
end if
end if
End If
Next
end if
// ------------------------------------------------------------------------------------------------
// now we need to generate all the CORRECT information from the stored GUIDS (see u_dw.other event):
// ------------------------------------------------------------------------------------------------
oleobject lole_item, lole_saveAs, lole_nameSpace
//string ls_body, ls_msg, ls_from, ls_to, ls_cc, ls_bcc, ls_name
string ls_subject, ls_fName, ls_entryID, is_empty[]
int li_rc
oleobject lole_outlook_app
oleobject loleNameSpace
try
lole_outlook_app = create oleobject
setpointer(hourglass!)
If lole_outlook_app.ConnectToNewObject("Outlook.Application") <> 0 Then
gnv_app.inv_error.of_Message( "cannot_log_onto_mail" )
gnv_app.of_debug("Outlook: cannot connect to outlook.application - constructor")
if lb_reset then
gnv_app.is_open_responseWindow = ""
end if
return -1 // v2, mjl, 07/07/20: instead of return without a value
End If
loleNameSpace = lole_outlook_app.GetNameSpace("MAPI")
string ls_dir
// store all of the dropped / selected files:
FOR ll_i = 1 to Upperbound(adw.is_dropped_fileGUIDS)
// v3, mjl, 25/05/21: due to office 64 bit issues we now use OLE to get the selected emails:
lole_item = loleNameSpace.GetItemFromID(adw.is_dropped_fileGUIDS[ll_i])
ls_subject = lole_item.subject
if isnull(ls_subject) then ls_subject = ""
ls_subject = trim(ls_subject)
if ls_subject = "" then
ls_subject = "Untitled" // same as when on 32 bit
end if
ls_dir = gnv_app.is_win_temp_dir + string(today(), 'yyyymmddhhmmssfff') + '-' + string(ll_i) // 2021/05/26 08:35:43.0042-1
if not directoryExists(ls_dir) then
createDirectory(ls_dir)
end if
//file names cannot contain any of these characters: |\/:*?"<>
// W1, mjl, 24/03/23: we now have a function to replace the invalid characters:
f_replaceInvalidCharactersFileName(ref ls_subject, "_")
// check how many characters are left for the subject before reaching windows max. length of 255:
// (in reality the limit would be 260 (unless you're on a very old windows, but table field is limited to 255 anyway).
if len(ls_Dir + "\" + ls_subject + ".msg") > 255 then
li_file_len = 255 - len(ls_Dir + "\" + ".msg")
ls_subject = mid(ls_subject, 1, li_file_len)
end if
ls_fName = ls_Dir + "\" + ls_subject + ".msg"
lole_item.SaveAs(ls_fName, 3) // iolMsg = 3
adw.is_dropped_fileNames[ll_i] = ls_fName
adw.is_delete_directories[ll_i] = ls_Dir
NEXT
catch ( runtimeError runtErro)
// do nothing
if isvalid(lole_outlook_app) then
lole_outlook_app.disconnectobject( )
destroy lole_outlook_app
if lb_reset then
gnv_app.is_open_responseWindow = ""
end if
return -1
end if
finally
lole_outlook_app.disconnectobject( )
if isvalid(lole_item) then
destroy lole_item
end if
if isvalid(loleNameSpace) then
destroy loleNameSpace
end if
destroy lole_outlook_app
end try
end if
// v2, mjl, 20/04/20:
string ls_errors[], ls_note
string ls_item_id, ls_customer, ls_destination, ls_file
long ll_selectedRows[], ll_maxRows, ll_oleref_id[]
integer li_ret
ll_maxRows = adw.of_getselectedrownumbers(ref ll_selectedRows)
if ll_maxRows = 0 then
adw.event POST ue_postDropFiles()
//messagebox('Information', 'You have to select at least one row', information!)
// v5, mjl, use w_message instead of messagebox(), so the window will be brought to front:
gnv_app.inv_error.of_setstyle(gnv_app.inv_error.PFCWINDOW)
gnv_app.inv_error.of_message('select_at_least_one_row')
gnv_app.inv_error.of_setstyle(gnv_app.inv_error.DEFAULT)
if lb_reset then
gnv_app.is_open_responseWindow = ""
end if
return 0
end if
if as_noteType <> 'QN' then // only if it's not a query note:
w_master lw
adw.of_getParentWindow(lw)
Open(w_select_attach_category, lw)
is_attach_type = message.stringparm
if is_attach_type = '[cancelled]' then
adw.event POST ue_postDropFiles()
if lb_reset then
gnv_app.is_open_responseWindow = ""
end if
return 0
end if
end if
adw.event POST ue_postDropFiles()
ls_archDir = gnv_app.is_archivedir
if right(ls_archDir, 1) <> '\' then
ls_archDir += '\'
end if
// insert all needed OLE_PRINTDET records.
for ll_i = 1 to long(adw.iul_dropped_files)
setpointer(hourglass!)
INSERT into ole_printdet (ascii_file, template, ole_type) // JRW 06/07/01
VALUES (NULL,NULL, NULL ); // JRW 06/07/01
if SQLCA.SQLCODE <> 0 then
ls_errors[1] = string( SQLCA.SQLCode )
ls_errors[2] = string( SQLCA.SQLDBCODE )
ls_errors[3] = SQLCA.SQLERRTEXT
gnv_app.inv_error.of_message( "database_error", ls_errors[] )
SQLCA.of_rollback()
adw.event POST ue_postDropFiles()
if lb_reset then
gnv_app.is_open_responseWindow = ""
end if
return -1
end if
// Get the sequence number from the table so we can create the appropriate
// rows in the stored procedure and assign ascii values to the ole_template
ll_oleref_id[ll_i] = SQLCA.of_get_seqnumber( "OLE_PRINTDET_SEQ", "CURR" )
if ll_oleref_id[ll_i] < 1 then
// let's try again with a delay:
yield()
sleep(2)
ll_oleref_id[ll_i] = SQLCA.of_get_seqnumber( "OLE_PRINTDET_SEQ", "CURR" )
if SQLCA.SQLCODE <> 0 then
ls_errors[1] = string( sqlca.SQLcode )
ls_errors[2] = string( sqlca.SQLdbcode )
ls_errors[3] = sqlca.SQLErrText
SQLCA.of_rollback()
gnv_app.inv_error.of_message( "database_error", ls_errors[] )
adw.event POST ue_postDropFiles()
if lb_reset then
gnv_app.is_open_responseWindow = ""
end if
return -1
end if
if ll_oleref_id[ll_i] < 1 then
ls_errors[1] = "OLE_PRINTDET_SEQ"
gnv_app.inv_error.of_message( "cannot_read_seq", ls_errors[] )
SQLCA.of_rollback()
adw.event POST ue_postDropFiles()
if lb_reset then
gnv_app.is_open_responseWindow = ""
end if
return -1
end if
end if
ls_file = mid(adw.is_dropped_fileNames[ll_i], lastPos(adw.is_dropped_fileNames[ll_i], '\') + 1)
ls_destination = ls_archDir + string(ll_oleref_id[ll_i]) + "_" + ls_file // v3, mjl, 01/03/21: was string(ll_oleref_id)
// we might have to shorten the filename before renaming the folder
if len(ls_destination) > 255 then
int li_chopOff
li_chopOff = len(ls_destination) - 255 + 4 // plus 4 to cut off ".msg"
ls_destination = mid(ls_destination, 1, len(ls_destination) - li_chopOff) + ".msg"
end if
li_ret = FileCopy( adw.is_dropped_fileNames[ll_i], ls_destination, TRUE)
if li_ret = -1 then
SQLCA.of_rollback()
Messagebox("Error", 'Error while copying from source file:~r~n"' + adw.is_dropped_fileNames[ll_i] + '".', StopSign!)
adw.event POST ue_postDropFiles()
return -1
elseif li_ret = -2 then
SQLCA.of_rollback()
Messagebox("Error", 'Error while copying to destination file: "' + ls_destination + '".', StopSign!)
adw.event POST ue_postDropFiles()
return -1
end if
adw.is_dropped_fileNames[ll_i] = ls_destination
ls_note += ls_destination + "~r~n"
setpointer(hourglass!)
update ole_printdet
set ascii_file = :ls_destination,
ole_type = 'U',
active = 'Y'
WHERE oleref_id = :ll_oleref_id[ll_i];
if SQLCA.SQLCODE <> 0 then
ls_errors[1] = string( sqlca.SQLcode )
ls_errors[2] = string( sqlca.SQLdbcode )
ls_errors[3] = sqlca.SQLErrText
SQLCA.of_rollback()
gnv_app.inv_error.of_message( "database_error", ls_errors[] )
adw.event POST ue_postDropFiles()
return -1
end if
next
// insert a note for each selected row:
setnull(ls_item_id)
string ls_assoc_ind
boolean lb_assoc_ind
long ll_qry_id
setnull(ll_qry_id)
for ll_i = 1 to ll_maxRows
//insert a note
// all need the customer
if adw.dataobject = "d_trans_list" then
ls_customer = adw.object.item_customer[ll_selectedRows[ll_i]]
else
ls_customer = adw.object.customer[ll_selectedRows[ll_i]]
end if
setnull(ll_qry_id)
setnull(ls_item_id)
choose case as_noteType
case 'TN'
if adw.dataobject = "d_trans_list" then
ls_item_id = adw.object.item_trans[ll_selectedRows[ll_i]]
adw.object.trans_attach[ll_selectedRows[ll_i]] = 'Y'
else
ls_item_id = adw.object.item_no[ll_selectedRows[ll_i]]
end if
// case 'CN' // already set, so commented.
// ls_customer = adw.object.customer[ll_selectedRows[ll_i]]
case 'QN'
if adw.dataobject = "d_work_list" then
ll_qry_id = adw.object.master_id[ll_selectedRows[ll_i]]
ls_assoc_ind = adw.object.master_assocind[ll_selectedRows[ll_i]]
else
ll_qry_id = adw.object.qry_id[ll_selectedRows[ll_i]]
ls_assoc_ind = adw.object.assoc_ind[ll_selectedRows[ll_i]]
end if
lb_assoc_ind = false
if ls_assoc_ind = 'Y' then
lb_assoc_ind = true
// associated to a transaction, we have to fill both "customer" and "item_no" in cc_notehdr
if adw.dataobject = "d_work_list" then
ls_item_id = adw.object.master_transno[ll_selectedRows[ll_i]]
elseif adw.dataobject = 'd_ic_query' then
ls_item_id = adw.object.transaction_no[ll_selectedRows[ll_i]]
else
ls_item_id = adw.object.qry_transno[ll_selectedRows[ll_i]]
end if
end if
end choose
if this.of_dropped_Notes(ls_item_id, ls_customer, ll_qry_id, lb_assoc_ind, ls_note, ll_oleref_id, adw, as_noteType) = -1 then
adw.event POST ue_postDropFiles()
return -1 // rollback has already been done
end if
next
string ls_errorParm[]
choose case as_noteType
case 'TN'
if adw.iul_dropped_files = 1 then
// '1 E-mail has been attached for %S %S'
ls_errorParm[1] = string(ll_maxRows)
ls_errorParm[2] = "transaction(s)."
gnv_app.inv_error.of_message('attach_email', ls_errorParm)
else
// '%S E-mails have been attached for %S %S',
ls_errorParm[1] = string(adw.iul_dropped_files)
ls_errorParm[2] = string(ll_maxRows)
ls_errorParm[3] = "transaction(s)."
gnv_app.inv_error.of_message('attach_emails', ls_errorParm)
end if
case 'CN'
if adw.iul_dropped_files = 1 then
// '1 E-mail has been attached for %S %S'
ls_errorParm[1] = string(ll_maxRows)
ls_errorParm[2] = "customer(s)."
gnv_app.inv_error.of_message('attach_email', ls_errorParm)
else
// '%S E-mails have been attached for %S %S',
ls_errorParm[1] = string(adw.iul_dropped_files)
ls_errorParm[2] = string(ll_maxRows)
ls_errorParm[3] = "customer(s)."
gnv_app.inv_error.of_message('attach_emails', ls_errorParm)
end if
case 'QN'
if adw.iul_dropped_files = 1 then
// '1 E-mail has been attached for %S %S'
ls_errorParm[1] = string(ll_maxRows)
ls_errorParm[2] = "query/queries."
gnv_app.inv_error.of_message('attach_email', ls_errorParm)
else
// '%S E-mails have been attached for %S %S',
ls_errorParm[1] = string(adw.iul_dropped_files)
ls_errorParm[2] = string(ll_maxRows)
ls_errorParm[3] = "query/queries."
gnv_app.inv_error.of_message('attach_emails', ls_errorParm)
end if
end choose
sqlca.of_commit()
adw.event POST ue_postDropFiles()
return 1
Thanks also for the sample application. it would look really good on CodeXchange :)
regards.
regards