Project

General

Profile

Bug #4263 » wintir.rb

SamTreweek (Samuel Treweek), 01/11/2011 09:43 PM

 
#Wintir is based on the guitest and watir automation
require "Win32API"
require 'win32ole'
#require "cguitest"


module Wintir
module GuiTest
#Find Window
FindWindow = Win32API.new('user32', 'FindWindow', ["P", "P"], "L")
#Find sub windows
FindWindowEx = Win32API.new('user32', 'FindWindowEx', ['P'] * 4, 'L')
#Get Some Extra Details
GetClientRect = Win32API.new('user32','GetClientRect','LP','I')
GetWindowRect = Win32API.new('user32','GetWindowRect','LP','I')
class Rect
# TODO - rather than having Rect know how to unpack the buffer, the caller should
# do that, and then pass the 4 parameters. This decouples Rect from knowledge of
# how the buffer is packed.
def initialize(buf)
@left,@top,@right,@bottom = buf.unpack("llll")
width
height
#puts @left,@top,@right,@bottom
end
attr_accessor :left, :top, :right, :bottom

def width
@width = @right - @left
#puts @right - @left
end
attr_accessor :width

def height
@height = @bottom - @top
#puts @bottom - @top
end
attr_accessor :height
end
def assign_com how, what
#Find window's handle
com = FindWindow.call(how, what)
query_window com
puts com
return com
end
def query_window com
buf = "\0" * 16
GetWindowRect.call(com, buf)
@Rect = Rect.new(buf)
end
end
end

module Wintir
class ObjectAssert
SendMessage = Win32API.new("user32", "SendMessage", ['L'] * 4, 'L')
FindWindowEx = Win32API.new('user32', 'FindWindowEx', ['P'] * 4, 'L')
#Does the object exist
def object_exists(obj)
#puts obj.com
obj_id = FindWindowEx.call(obj.com,0,obj.name.to_s,obj.caption.to_s)
@obj_id = obj_id
return obj_id
end
attr_accessor :left, :top, :right, :bottom, :obj_id
#Object Visible/Enabled
def object_style(obj)
#puts obj
end
end
end


module Wintir
class DialogWindow
FindWindowEx = Win32API.new('user32', 'FindWindowEx', ['P'] * 4, 'L')
GetWindowTextA = Win32API.new('user32','GetWindowTextA','LPI','I')
SendMessageA = Win32API.new('user32','SendMessageA','LIIP','I')
def initialize(container, dialog_name)
#puts container
@container = container
get_dialog(dialog_name)
end
attr_accessor :com
def get_dialog(dialog_name)
#create dialog_title space
dialog_title = "".center(256)
#32770 is the name for a dialog - brilliant!
d_hwnd = FindWindowEx.call(0, 0, "#32770", 0)
#Confirm the dialog_name is the one we're after
GetWindowTextA.call(d_hwnd, dialog_title, 200)
#puts dialog_name
#puts d_hwnd
#puts dialog_title.rstrip
@com = d_hwnd
end
def close
SendMessageA.call(self.com, 16, 0, 0)
end
def click_button
#puts "click the button then"
end

def static_text
puts self.com
t_hwnd = FindWindowEx.call(self.com, 0, 'Static', '')
puts "id #{t_hwnd}"
end

attr_accessor :name, :attached_text, :zorder, :caption
def button(describe = nil)
@name=describe[:name]
@attached_text = describe[:attached_text]
@zorder = describe[:zorder]
@caption = describe[:caption]
Button.new(self, describe[:caption], describe[:name], describe[:attached_text], describe[:zorder])
end
def combo_list(describe = nil)
@name=describe[:name]
@attached_text = describe[:attached_text]
@zorder = describe[:zorder]
@caption = describe[:caption]
Combo_List.new(self, describe[:caption], describe[:name], describe[:attached_text], describe[:zorder])
end
def list_box(describe=nil)
@name=describe[:name]
@attached_text = describe[:attached_text]
@zorder = describe[:zorder]
@caption = describe[:caption]
List_Box.new(self, describe[:caption], describe[:name], describe[:attached_text], describe[:zorder])
end
def static(describe = nil)
@static = describe
@name=describe[:name]
@attached_text = describe[:attached_text]
@zorder = describe[:zorder]
@caption = describe[:caption]
Static_Text.new(self, describe[:caption], describe[:name], describe[:attached_text], describe[:zorder])
end
def tabs(describe=nil)
@name=describe[:name]
@attached_text = describe[:attached_text]
@zorder = describe[:zorder]
@caption = describe[:caption]
TabControl.new(self, describe[:caption], describe[:name], describe[:attached_text], describe[:zorder])
end
end
class Dialog < DialogWindow
INPUT_TYPES = ["caption", "button", "attached_text", "zorder"]
end
end

#FileMenuInput Class
module Wintir
class FileMenuInput
FindWindowEx = Win32API.new('user32', 'FindWindowEx', ['P'] * 4, 'L')
SendMessageAB = Win32API.new('user32', 'SendMessage', ["L", "L", "P", "P"], "L")
SendMessageA = Win32API.new('user32','SendMessageA','LIIP','I')
PostMessageA = Win32API.new('user32','PostMessageA','LIIL','I')
GetMenu = Win32API.new('user32','GetMenu','L','L')
GetMenuA = Win32API.new('user32','GetMenu','I', 'I')
GetMenuItemCount = Win32API.new('user32','GetMenuItemCount','L','I')
GetMenuStringA = Win32API.new('user32','GetMenuStringA','LIPII','I')
GetMenuString = Win32API.new('user32','GetMenuString','LIPII','I')
GetSubMenu = Win32API.new('user32','GetSubMenu','LI','L')
GetMenuItemID = Win32API.new('user32','GetMenuItemID','LI','I')
WM_SETTEXT = 0x000C
def initialize(container, menu_path)
#puts container.com
@container = container
get_application_menu(menu_path)
end
attr_accessor :container
def click
#puts "click"
end

def get_application_menu(menu_path)
#Delare menu item false
top_level_menu_item = false
sub_level_menu_item = false
mi = menu_path.split('>')
#Get Menu
h_wnd_menu = GetMenuA.call(container.com)
#puts h_wnd_menu
menu_count = GetMenuItemCount.call(h_wnd_menu)
##puts menu_count
top_menu = "".center(256)
sub_name = "".center(256)
sub_l_name = "".center(256)
for i in 0..(menu_count-1) do
GetMenuString.call(h_wnd_menu, i, top_menu, top_menu.length, 1024)
top_menu_item = top_menu.rstrip
##puts top_menu_item.to_s
replace_from = '&'
replace_to = ''
top_menu_item = top_menu_item.gsub(/#{replace_from}/, replace_to)
if( /#{mi[0]}/.match(top_menu_item.to_s) )
#boolean check
##puts "Found it #{mi[0]}"
##puts top_menu_item
top_level_menu_item = true
end

h_view = GetSubMenu.call(h_wnd_menu, i)
# #puts h_view
GetMenuString.call(h_view, i, sub_name, sub_name.length, 1024)
# #puts sub_name.strip
menu_count1 = GetMenuItemCount.call(h_view)
for j in 0..(menu_count1-1) do
GetMenuString.call(h_view, j, sub_l_name, sub_l_name.length, 1024)
sub_menu_item = sub_l_name.rstrip
##puts sub_menu_item.to_s
##puts sub_l_name.strip
menu_item = GetMenuItemID.call(h_view, j)
##puts menu_item
sub_menu_item = sub_menu_item.gsub(/#{replace_from}/, replace_to)
##puts sub_menu_item.to_s
if( /#{mi[1]}/.match(sub_menu_item.to_s) )
#boolean check
##puts sub_menu_item
##puts "Found it #{mi[1]}"
sub_level_menu_item = true
end

if top_level_menu_item && sub_level_menu_item
##puts menu_item
##puts h_wnd
#Use PostMessage so as not to wait for confirmation
PostMessageA.call(@container.com, 273, menu_item, 0)
top_level_menu_item = false
sub_level_menu_item = false
#puts "Found menu: #{mi[0]} > #{mi[1]}"
end
#Reset the holding variable to blank
#open_file(sub_l_name.strip)
sub_l_name = "".center(256)
end

#Reset the holding variable to blank
sub_name = "".center(256)
#open_file(sub_l_name.strip)
end

end
end
class Filemenu < FileMenuInput
INPUT_TYPES = ["caption", "name", "attached_text", "zorder"]
end
end

#Combo Box Class
module Wintir
class Combolist
FindWindowEx = Win32API.new('user32', 'FindWindowEx', ['P'] * 4, 'L')
GetComboBoxInfo = Win32API.new('user32','GetComboBoxInfo','LP','L')
SendMessageA = Win32API.new('user32','SendMessageA','LIIP','I')
GetClientRect = Win32API.new('user32','GetClientRect','LP','I')
GetWindowRect = Win32API.new('user32','GetWindowRect','LP','I')
#Messages
CB_SELECTSTRING = 333
CB_GETCOUNT = 326
CB_GETDROPPEDSTATE = 343
CB_GETLBTEXT = 328
CB_GETLBTEXTLEN = 329
include Wintir::GuiTest
def initialize(container, caption, name, attached_text, zorder)
find_combo(container)
check_attached_text(self.cb_hwnd, attached_text)
check_attached_text(container.com, attached_text)
#puts caption
end
def check_attached_text(obj_hwnd, attached_text)
#puts attached_text
buf = "\0" * 16
GetClientRect.call(obj_hwnd, buf)
@Rect = Rect.new(buf)
end
def select_selection(combo_selection)
end
attr_accessor :name, :attached_text, :zorder, :caption
def find_combo(container)
cb_hwnd = FindWindowEx.call(container.com,0,container.name.to_s,container.caption.to_s)
@cb_hwnd = cb_hwnd

#Getting the ComboInfo on hold
#buf = "\0" * 255
#GetComboBoxInfo.call(c_hwnd, buf)
#@combo = ComboInfo.new(buf)
#puts cb_hwnd
end
attr_accessor :cb_hwnd
def get_combo_count
cb_count = SendMessageA.call(self.cb_hwnd, 326, 0, 0)
return cb_count
end
def select_string(string)
#Return Position by integer
cb_selectstring = SendMessageA.call(self.cb_hwnd, CB_SELECTSTRING, -1, string)
return cb_selectstring
end
def get_state
#Return 1=True
cb_getdroppedstate = SendMessageA.call(self.cb_hwnd, CB_GETDROPPEDSTATE, 0, 0)
return cb_getdroppedstate
end
#ToDO. Failing
def get_cb_text(position)
buf = "\0" * 16
cb_getlbtext = SendMessageA.call(self.cb_hwnd, CB_GETLBTEXT, position, buf)
a = buf.unpack("l")
return cb_getlbtext
end
def get_cb_text_len(position)
buf = "".center(255)
cb_getlbtextlen = SendMessageA.call(self.cb_hwnd, CB_GETLBTEXTLEN, position, buf)
return cb_getlbtextlen
end
end
class Combo_List < Combolist
INPUT_TYPES = ["caption", "name", "attached_text", "zorder"]
end
end

#Static Text Class
module Wintir
class Static
FindWindowEx = Win32API.new('user32', 'FindWindowEx', ['P'] * 4, 'L')
GetClientRect = Win32API.new('user32','GetClientRect','LP','I')
GetWindowRect = Win32API.new('user32','GetWindowRect','LP','I')
include Wintir::GuiTest
def initialize(container, caption, name, attached_text, zorder)
@com = container.com
find_static_text(container)
end
def find_static_text(container)
st_hwnd = FindWindowEx.call(container.com,0,container.name.to_s,container.caption.to_s)
get_location_and_size(st_hwnd)
#puts st_hwnd
end
def get_location_and_size(obj_hwnd)
#GetWindowRect details
buf = "\0" * 16
GetWindowRect.call(obj_hwnd, buf)
@WindowRect = Rect.new(buf)
#GetClientRect details
buf = "\0" * 16
GetClientRect.call(obj_hwnd, buf)
@ClientRect = Rect.new(buf)
end
end
class Static_Text < Static
INPUT_TYPES = ["caption", "name", "attached_text", "zorder"]
end
end

module Wintir
class TabControl

SendMessageA = Win32API.new('user32','SendMessageA','LIIP','I')
FindWindowEx = Win32API.new('user32', 'FindWindowEx', ['P'] * 4, 'L')
TCM_GETITEMCOUNT = 4868
TCM_GETCURSEL = 4875
TCM_SETCURSEL = 4876
def initialize(container, caption, name, attached_text, zorder)
@com = container.com
find_tab_control(container)
#get_current_tab(container)
#puts caption
end
#find the tab control described
def find_tab_control(container)
tc_hwnd = FindWindowEx.call(container.com,0,container.name.to_s,container.caption.to_s)
@tc_hwnd = tc_hwnd
end
attr_accessor :tc_hwnd
def get_current_tab
cur_tab = SendMessageA.call(self.tc_hwnd, TCM_GETCURSEL, 0, 0)
#puts cur_tab
return cur_tab
end

def set_tab(index)
SendMessageA.call(self.tc_hwnd, TCM_SETCURSEL, index, 0)
end
def get_tab_count
tb_count = SendMessageA.call(self.tc_hwnd, TCM_GETITEMCOUNT, 0, 0)
return tb_count
end
class Tab_Control < TabControl
INPUT_TYPES = ["caption", "name", "attached_text", "zorder"]
end
end
end

#List Box Class
module Wintir
class Listbox
FindWindowEx = Win32API.new('user32', 'FindWindowEx', ['P'] * 4, 'L')
GetListBoxInfo = Win32API.new('user32','GetListBoxInfo','LP', 'L')
SendMessageA = Win32API.new('user32','SendMessageA','LIIP','I')
def initialize(container, caption, name, attached_text, zorder)
@com = container.com
find_list(container)
#puts caption
end
def select_selection(combo_selection)
end
attr_accessor :name, :attached_text, :zorder, :caption
def find_list(container)
lb_hwnd = FindWindowEx.call(container.com,0,container.name.to_s,container.caption.to_s)
@lb_hwnd = lb_hwnd
no_lb_items = GetListBoxInfo.call(lb_hwnd, container.com)
@no_lb_items = no_lb_items
#puts no_lb_items
end
def find_string_item(string)
lp_Result = SendMessageA.call(self.lb_hwnd, 399, -1, string)
#puts lp_Result
end
def select_list_box_value(value)
SendMessageA.call(self.lb_hwnd, 390, value, 0)
end
attr_accessor :lb_hwnd, :no_lb_items
end
class List_Box < Listbox
INPUT_TYPES = ["caption", "name", "attached_text", "zorder"]
end
end

#Input Elements
module Wintir
class InputElement
FindWindowEx = Win32API.new('user32', 'FindWindowEx', ['P'] * 4, 'L')
SendMessageAB = Win32API.new('user32', 'SendMessage', ["L", "L", "P", "P"], "L")
SendMessageA = Win32API.new('user32','SendMessageA','LIIP','I')
PostMessageA = Win32API.new('user32','PostMessageA','LIIL','I')
GetWindowRect = Win32API.new('user32','GetWindowRect','LP','I')
WM_SETTEXT = 0x000C
#For setting object color - temp
#include Wintir::SetObjectColour
def intValue
@value
end
def initialize(container, caption, name, attached_text, zorder)
#set_container container
if is_caption(caption) == true
#puts "name is good"
end
if is_name(name) == true
#puts "name is good"
end
if is_attached_text(attached_text) == true
#puts "attached_text is good"
end
if is_zorder(zorder) == true
#puts "zorder is good"
end
#set the value of the text box - Note: Might have to use PostMessage
def set(value)
#temp location for setting background object color
col = Wintir::SetObjectColour.new(self.obj_id)
col.color_on(self.obj_id)
SendMessageA.call(self.obj_id, WM_SETTEXT, 0, value)
end
def close
SendMessageA.call(self.obj_id, 16, 0, 0)
end
def click
#puts "click #{@obj_id}"
PostMessageA.call(@obj_id, 245, 0, 0)
end
com = ObjectAssert.new
com.object_exists(container)
@obj_id =com.obj_id
#super(nil)
end
attr_accessor :obj_id
def is_caption(caption)
if caption != nil and caption != ""
##puts "A real name #{name}"
return true
end
end
def is_name(name)
if name != nil and name != ""
return true
end
end
def is_attached_text(attached_text)
if attached_text != nil and attached_text != ""
##puts "Real text #{attached_text}"
buf = "\0" * 16
GetWindowRect.call(com, buf)
@Rect = Rect.new(buf)
return true
end
end
def is_zorder(zorder)
if zorder != nil
##puts "Zorder is #{zorder}"
return true
end
end
end
class TextField < InputElement
INPUT_TYPES = ["caption", "name", "attached_text", "zorder"]
end
class Button < InputElement
INPUT_TYPES = ["caption", "button", "attached_text", "zorder"]
end
end

#Container Class
module Wintir
module Container
SendMessageA = Win32API.new('user32','SendMessageA','LIIP','I')
#text_field (describe) - Describe Edit objects using
#
#:name, the real name of the object
# Usage :name => "txtFirstname"
#
#:attached_text, the text above or to the left of the field
# Usage :attached_text => "Firstname"
#
#zorder, the position of the edit field on the form, starting from top left -> bottom right
# Useage :zorder => 0
def text_field(describe = nil)
@name = describe[:name]
@attached_text = describe[:attached_text]
@zorder = describe[:zorder]
@caption = describe[:caption]
TextField.new(self, describe[:caption], describe[:name], describe[:attached_text], describe[:zorder] )
end
attr_accessor :name, :attached_text, :zorder, :caption
def button(describe = nil)
@name=describe[:name]
@attached_text = describe[:attached_text]
@zorder = describe[:zorder]
@caption = describe[:caption]
Button.new(self, describe[:caption], describe[:name], describe[:attached_text], describe[:zorder])
end
attr_accessor :menu_path
def close
SendMessageA.call(self.com, 16, 0, 0)
end
def file_menu(describe = nil)
@menu_path=describe
Filemenu.new(self, describe[:menu_path])
end
attr_accessor :dialog_name
def dialog(describe=nil)
@dialog_name = describe
Dialog.new(self, describe[:dialog_name])
end
def combo_list(describe = nil)
@combo=describe
Combolist.new(self, describe[:combo])
end
def static(describe = nil)
@static = describe
Static_Text.new(self, describe[:caption])
end
end
end

module Wintir

class Com
CreateProcess = Win32API.new('kernel32','CreateProcess','PPPPILPPPP','I')
WaitForInputIdle = Win32API.new('user32','WaitForInputIdle','II','I')
GetDesktopWindow = Win32API.new('user32','GetDesktopWindow','V','L')
GetWindow = Win32API.new('user32','GetWindow','LI','L')
GetWindowThreadProcessId = Win32API.new('user32','GetWindowThreadProcessId', 'LP', 'L')
GetParent = Win32API.new('user32','GetParent','L','L')
GetForegroundWindow = Win32API.new('user32','GetForegroundWindow', 'V', 'L')
include Wintir::Container
include Wintir::GuiTest

def pid
pid = [0].pack('L')
hwnd = GetForegroundWindow.call
GetWindowThreadProcessId.call(hwnd, pid)
pid = pid.unpack('L')[0]
end

def create_application_window(what)
create_process(nil, what)
end
def create_process(lpApplicationName, lpCommandLine, lpCurrentDirectory=nil,
dwMilliseconds=60000)
lpStartupInfo = [68].pack("L") + "\0" * 64
lpProcessInformation = [0,0,0,0].pack('LLLL')
CreateProcess.call(lpApplicationName, lpCommandLine, nil, nil, 1, 0, nil, lpCurrentDirectory, lpStartupInfo, lpProcessInformation)
hProcess = lpProcessInformation[8,4].unpack('L').first
com = 0
process_id_count = 0
#Not a great plan but WaitForInputIdle is failing
while com == 0 or process_id_count != 10
com = gethwndfromprocessid(hProcess)
#counter - so that this isn't endless
process_id_count = process_id_count + 1
end
#puts com
com = GetForegroundWindow.call
ret = waitForInputIdle(hProcess, dwMilliseconds)
##puts ret
#if dwMilliseconds != 0 and (ret = waitForInputIdle(hProcess, dwMilliseconds)) != 0
# raise "createProcess(#{lpCommandLine},#{lpCurrentDirectory},#{dwMilliseconds}):" +
# " waitForInputIdle returns #{ret}"
#end
@com = com
end
GW_CHILD = 5
GW_HWNDNEXT = 2
def gethwndfromprocessid(hProcess)
hWnd = GetDesktopWindow.call()
window_found = false
hWndProcess = [0].pack('L')

while not window_found and hWnd != 0
#Get the Child Window
tmp = hWnd
hWnd = GetWindow.call(hWnd, GW_CHILD)
if hWnd != 0 then
dl = GetWindowThreadProcessId.call(hWnd, hWndProcess)
hWndProcess = hWndProcess.unpack('L')[0]

if hWndProcess == hProcess then
window_found = true
#puts "window_found"
end
hWndProcess = [0].pack('L')
else
hWnd = tmp
hWnd = GetWindow.call(hWnd, GW_HWNDNEXT)
if hWnd != 0 then
dl = GetWindowThreadProcessId.call(hWnd, hWndProcess)
hWndProcess = hWndProcess.unpack('L')[0]
if hWndProcess == hProcess then
window_found = true
#puts "window_found"
end
hWndProcess = [0].pack('L')
else
hWnd = tmp
hWnd = GetParent.call(hWnd)
if hWnd != 0 then
branch_found = false
while not branch_found and not window_found and hWnd != 0
tmp = hWnd
hWnd = GetWindow.call(hWnd, GW_HWNDNEXT)
if hWnd != 0 then
branch_found = true
dl = GetWindowThreadProcessId.call(hWnd, hWndProcess)
hWndProcess = hWndProcess.unpack('L')[0]
if hWndProcess == hProcess then
window_found = true
#puts "window_found"
end
hWndProcess = [0].pack('L')
else
hWnd = tmp
hWnd = GetParent.call(hWnd)
end
end
end
end
end
end
@com = hWnd
return hWnd
end
INFINITE = 0xffffffff # Infinite timeout
def waitForInputIdle(hProcess, dwMilliseconds=INFINITE)
WaitForInputIdle.call(hProcess, dwMilliseconds)
end
attr_accessor :obj_class, :name, :com

def initialize_options
#puts "init opt"
end

def _attach_init describe
@obj_class = describe[:obj_class]
@name = describe[:name]
attach_com_window @obj_class, @name
initialize_options
wait
end

def self.create describe

@lpApplicationName = describe[:name]
@lpCommandLinet = describe[:command_line]

com = new describe
com._new_window_init @lpApplicationName
com
end

def self.attach describe
#Attach the how, what variants
com = new true
com._attach_init(describe)
com
end

def initialize describe
#puts describe
# _new_window_init describe[:name]
end

attr_accessor :name, :command_line

def _new_window_init what
create_process(nil, what)
end

def self._find(how, what)
ieTemp = ""
return ieTemp
end

def wait(no_sleep=false)
#puts "wait"
end

def log(what)
#puts "log"
@logger.debug(what) if @logger
end

def attach_com_window how, what
log "Seeking Window with #{how}: #{what}"
#puts "attach com window"
comTemp = nil
#begin
# Wintir::until_with_timeout do
comTemp = assign_com(how, what)
# end
#rescue TimeOutException
# raise NoMatchingWindowFoundException,
# "Unable to locate a window with #{how} of #{what}"
#end
@com = comTemp
#return @com
end
private :attach_com_window

end
end


#ComboInfo Class - Needs further investigation
module Wintir
class ComboInfo
def initialize(buf)
@cbSize,@rcItem,@stateButton,@hwndCombo,@hwndItem,@hwndList = buf.unpack("IPPIII")
#puts @cbSize
end
attr_accessor :cbSize,:rcItem,:rcItem,:stateButton,:hwndCombo,:hwndItem,:hwndList

end
end

module Wintir
class SetObjectColour
SendMessageA = Win32API.new('user32','SendMessageA','LIIP','I')
# SetBkColor = Win32API.new('user32', 'SetBkColor', 'LI','L')
GetWindowDC = Win32API.new('user32','GetWindowDC','L','L')
SetForegroundWindow = Win32API.new('user32','SetForegroundWindow','L','I')
GetDC = Win32API.new('user32','GetDC','L','L')
EM_SETBKGNDCOLOR = 0x0443
SET_COLOR_YELLOW = 0xDFFFA5
def initialize(com)
#ToDo check the object type for correct color change
#puts com
end
#Turn the background of the object color on
def color_on(com)
#yellow
color_on = true
color_on = SendMessageA.call(com, EM_SETBKGNDCOLOR, 0, SET_COLOR_YELLOW)
return color_on
end
#Protect from user setting background objects color status
#private :color_on
#Turn the background of the color off
def color_off
end
#Get the current color of the objects background
def get_object_bk_color(com)
#Setting the window to focus call to pixel/color
SetForegroundWindow.call(com)
#Get the DC
hdc_source = GetDC.call(com)
#puts hdc_source
end
#Protect from user setting background objects color status
#private :color_off
end
end
(2-2/2)