lib/dde/monitor.rb in dde-0.2.2 vs lib/dde/monitor.rb in dde-0.2.8
- old
+ new
@@ -1,10 +1,12 @@
module DDE
# Class encapsulates DDE Monitor that prints all DDE transactions to console
class Monitor < App
+ attr_accessor :print, :calls
+
# Creates new DDE monitor instance
def initialize(init_flags=nil, &callback)
init_flags ||=
APPCLASS_MONITOR | # this is monitor
MF_CALLBACKS | # monitor callback functions
@@ -13,14 +15,79 @@
MF_HSZ_INFO | # monitor data handle activity
MF_LINKS | # monitor advise loops
MF_POSTMSGS | # monitor posted DDE messages
MF_SENDMSGS # monitor sent DDE messages
+ @calls = []
+
callback ||= lambda do |*args|
- p args.unshift(Win::DDE::TYPES[args.shift]).push(Win::DDE::FLAGS[args.pop])
- 1
+ time = Time.now.strftime('%T.%6N')
+ values = extract_values(*args)
+ @calls << [time, values]
+ puts "#{time} #{values}" if @print
+ DDE_FACK
end
-
+
super init_flags, &callback
+ end
+
+ def extract_values(*args)
+ values = args.map {|arg| interprete_value(arg)}
+
+ # if this is a MONITOR transaction, extract hdata using the DdeAccessData
+ if values.first == :XTYP_MONITOR
+ data_type = case values.last
+ when :MF_CALLBACKS
+ MonCbStruct #.new(dde_get_data(args[5]).first)
+ # cb:: Specifies the structure's size, in bytes.
+ # dwTime:: Specifies the Windows time at which the transaction occurred. Windows time is the number of
+ # milliseconds that have elapsed since the system was booted.
+ # hTask:: Handle to the task (app instance) containing the DDE callback function that received the transaction.
+ # dwRet:: Specifies the value returned by the DDE callback function that processed the transaction.
+ # wType:: Specifies the transaction type.
+ # wFmt:: Specifies the format of the data exchanged (if any) during the transaction.
+ # hConv:: Handle to the conversation in which the transaction took place.
+ # hsz1:: Handle to a string.
+ # hsz2:: Handle to a string.
+ # hData:: Handle to the data exchanged (if any) during the transaction.
+ # dwData1:: Specifies additional data.
+ # dwData2:: Specifies additional data.
+ # cc:: Specifies a CONVCONTEXT structure containing language information used to share data in different languages.
+ # cbData:: Specifies the amount, in bytes, of data being passed with the transaction. This value can be
+ # more than 32 bytes.
+ # Data:: Contains the first 32 bytes of data being passed with the transaction (8 * sizeof(DWORD)).
+
+ when :MF_CONV
+ MonConvStruct
+ when :MF_ERRORS
+ MonErrStruct
+ when :MF_HSZ_INFO
+ MonHszStruct
+ when :MF_LINKS
+ MonLinksStruct
+ else
+ MonMsgStruct
+ end
+
+ #casting DDE data pointer into appropriate struct type
+ struct_pointer, size = dde_get_data(args[5])
+ data = data_type.new(struct_pointer)
+
+ values = [values.first, values.last] + data.members.map do |member|
+ value = data[member] rescue 'plonk'
+ "#{member}: #{interprete_value(value)}"
+ end
+ end
+
+ values
+ end
+
+ def interprete_value(arg)
+ return arg unless arg.kind_of? Fixnum rescue return 'plAnk'
+ return 0 if arg == 0
+ #Trying to interpete arg as a DDE string
+ dde_query_string(@id, arg)\
+ || Win::DDE.constants(false).inject(nil) {|res, const| arg == Win::DDE.const_get(const) ? res || const : res }\
+ || arg
end
end
end
\ No newline at end of file