Hi, I see the Win32::Clipboard module has a WaitForChange() method that waits for a change in the Windows clipboard. I''d like to setup something similar for the win32-clipboard library, perhaps call it notify_change to match win32-eventlog. I looked at the implementation, and it''s similar to others I found online. But, it seems like it ought to be easier. Instead of RegisterClass(), CreateWindow(), etc, can''t we just use the handle of the current process instead of injecting a new Window into the clipboard chain? In any case, I''m not having much luck trying to implement this. I did add some methods to the Windows::Window::Classes module that might be necessary. Any help here would be greatly appreciated. In other news, it seems GetWindowLongPtr and SetWindowLongPtr are not exported by the runtime that ships with the one-click. Regards, Dan PS - It''s a shame they don''t provide a NotifyChangeClipboard() function to make life easier. :)
Hi, 2009/4/23 Daniel Berger <djberg96 at gmail.com>:> Hi, > > I see the Win32::Clipboard module has a WaitForChange() method that waits > for a change in the Windows clipboard. I''d like to setup something similar > for the win32-clipboard library, perhaps call it notify_change to match > win32-eventlog. > > I looked at the implementation, and it''s similar to others I found online. > But, it seems like it ought to be easier. Instead of RegisterClass(), > CreateWindow(), etc, can''t we just use the handle of the current process > instead of injecting a new Window into the clipboard chain? > > In any case, I''m not having much luck trying to implement this. I did add > some methods to the Windows::Window::Classes module that might be necessary. > Any help here would be greatly appreciated. > > In other news, it seems GetWindowLongPtr and SetWindowLongPtr are not > exported by the runtime that ships with the one-click. > > Regards, > > Dan > > PS - It''s a shame they don''t provide a NotifyChangeClipboard() function to > make life easier. :) >As you expected, here is a sample code :) require ''win32/api'' require ''windows/clipboard'' require ''windows/window/classes'' require ''windows/window/message'' require ''windows/library'' require ''windows/window'' require ''win32/clipboard'' include Win32 include Windows::Window include Windows::Window::Classes include Windows::Window::Message include Windows::Library include Windows::Clipboard handle = CreateWindow(''static'',''test'',0,0,0,0,0,0,0,0,0) my_wnd_proc = API::Callback.new(''LLLL'', ''L'') do |hwnd,uMsg,wParam,lParam| case uMsg when 0x0308 # WM_DRAWCLIPBOARD puts ''Clipboard Changed'' puts Clipboard.data next_viewer = GetWindowLongPtr(hwnd,GWL_USERDATA) if next_viewer != 0 PostMessage(next_viewer,uMsg,wParam,lParam) end r = 0 when 0x030D # WM_CHANGECBCHAIN puts ''WM_CHANGECBCHAIN'' next_viewer = lParam if next_viewer == wParam if next_viewer != 0 PostMessage(next_viewer,uMsg,wParam,lParam) end r = 0 else r = DefWindowProc(hwnd,uMsg,wParam,lParam) end r end old_wnd_proc = SetWindowLongPtr(handle,GWL_WNDPROC,my_wnd_proc.address) next_viewer = SetClipboardViewer(handle) SetWindowLongPtr(handle,GWL_USERDATA,next_viewer) msg = 0.chr * 100 while true while(PeekMessage(msg,handle,0,0,1)) TranslateMessage(msg) DispatchMessage(msg) end sleep 0.1 end In order to run this code, several changes are required. 1. GetWindowLongPtr and SetWindowLongPtr In 32bit Windows, GetWindowLongPtr and SetWindowLongPtr are just a macro of GetWindowLog and SetWindowLong. Modify windows/window/classes.rb like this would be enough: begin API.new(''GetWindowLongPtr'', ''LI'', ''L'', ''user32'') API.new(''SetWindowLongPtr'', ''LIP'', ''L'', ''user32'') rescue Win32::API::LoadLibraryError alias :GetWindowLongPtr :GetWindowLong alias :SetWindowLongPtr :SetWindowLong end 2. CreateWindow In recent version of user32.dll, CreateWindow is not a function but a macro of CreateWindowEx. Modify windows/window.rb something like this begin API.new(''CreateWindow'', ''PPLIIIILLLL'', ''L'', ''user32'') rescue Win32::API::LoadLibraryError def CreateWindow(lpClassName, lpWindowName, dwStyle, x, y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam) CreateWindowEx(0,lpClassName, lpWindowName, dwStyle, x, y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam) end def CreateWindowA(lpClassName, lpWindowName, dwStyle, x, y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam) CreateWindowExA(0,lpClassName, lpWindowName, dwStyle, x, y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam) end def CreateWindowW(lpClassName, lpWindowName, dwStyle, x, y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam) CreateWindowExW(0,lpClassName, lpWindowName, dwStyle, x, y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam) end end 3. GetUpdatedClipboardFormats GetUpdatedClipboardFormats is supported for Vista or later. Modify windows/clipboard.rb something like this begin API.new(''GetUpdatedClipboardFormats'', ''PIP'', ''I'', ''user32'') API.new(''AddClipboardFormatListener'', ''L'', ''B'', ''user32'') API.new(''RemoveClipboardFormatListener'', ''L'', ''B'', ''user32'') rescue Win32::API::LoadLibraryError # Windows Vista or later end Regards, Park Heesob
Heesob Park wrote:> Hi, > > 2009/4/23 Daniel Berger <djberg96 at gmail.com>: >> Hi, >> >> I see the Win32::Clipboard module has a WaitForChange() method that waits >> for a change in the Windows clipboard. I''d like to setup something similar >> for the win32-clipboard library, perhaps call it notify_change to match >> win32-eventlog. >> >> I looked at the implementation, and it''s similar to others I found online. >> But, it seems like it ought to be easier. Instead of RegisterClass(), >> CreateWindow(), etc, can''t we just use the handle of the current process >> instead of injecting a new Window into the clipboard chain? >> >> In any case, I''m not having much luck trying to implement this. I did add >> some methods to the Windows::Window::Classes module that might be necessary. >> Any help here would be greatly appreciated. >> >> In other news, it seems GetWindowLongPtr and SetWindowLongPtr are not >> exported by the runtime that ships with the one-click. >> >> Regards, >> >> Dan >> >> PS - It''s a shame they don''t provide a NotifyChangeClipboard() function to >> make life easier. :) >> > As you expected, here is a sample code :) > > require ''win32/api'' > require ''windows/clipboard'' > require ''windows/window/classes'' > require ''windows/window/message'' > require ''windows/library'' > require ''windows/window'' > require ''win32/clipboard'' > > include Win32 > include Windows::Window > include Windows::Window::Classes > include Windows::Window::Message > include Windows::Library > include Windows::Clipboard > > handle = CreateWindow(''static'',''test'',0,0,0,0,0,0,0,0,0) > > my_wnd_proc = API::Callback.new(''LLLL'', ''L'') do |hwnd,uMsg,wParam,lParam| > case uMsg > when 0x0308 # WM_DRAWCLIPBOARD > puts ''Clipboard Changed'' > puts Clipboard.data > next_viewer = GetWindowLongPtr(hwnd,GWL_USERDATA) > if next_viewer != 0 > PostMessage(next_viewer,uMsg,wParam,lParam) > end > r = 0 > when 0x030D # WM_CHANGECBCHAIN > puts ''WM_CHANGECBCHAIN'' > next_viewer = lParam if next_viewer == wParam > if next_viewer != 0 > PostMessage(next_viewer,uMsg,wParam,lParam) > end > r = 0 > else > r = DefWindowProc(hwnd,uMsg,wParam,lParam) > end > r > end > > old_wnd_proc = SetWindowLongPtr(handle,GWL_WNDPROC,my_wnd_proc.address) > next_viewer = SetClipboardViewer(handle) > SetWindowLongPtr(handle,GWL_USERDATA,next_viewer) > > msg = 0.chr * 100 > while true > while(PeekMessage(msg,handle,0,0,1)) > TranslateMessage(msg) > DispatchMessage(msg) > end > sleep 0.1 > end > > > In order to run this code, several changes are required. > 1. GetWindowLongPtr and SetWindowLongPtr > > In 32bit Windows, GetWindowLongPtr and SetWindowLongPtr are just a > macro of GetWindowLog and SetWindowLong. > Modify windows/window/classes.rb like this would be enough: > > begin > API.new(''GetWindowLongPtr'', ''LI'', ''L'', ''user32'') > API.new(''SetWindowLongPtr'', ''LIP'', ''L'', ''user32'') > rescue Win32::API::LoadLibraryError > alias :GetWindowLongPtr :GetWindowLong > alias :SetWindowLongPtr :SetWindowLong > end > > 2. CreateWindow > > In recent version of user32.dll, CreateWindow is not a function but a > macro of CreateWindowEx. > Modify windows/window.rb something like this > > begin > API.new(''CreateWindow'', ''PPLIIIILLLL'', ''L'', ''user32'') > rescue Win32::API::LoadLibraryError > def CreateWindow(lpClassName, lpWindowName, dwStyle, x, y, > nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam) > CreateWindowEx(0,lpClassName, lpWindowName, dwStyle, x, y, nWidth, > nHeight, hWndParent, hMenu, hInstance, lpParam) > end > def CreateWindowA(lpClassName, lpWindowName, dwStyle, x, y, > nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam) > CreateWindowExA(0,lpClassName, lpWindowName, dwStyle, x, y, nWidth, > nHeight, hWndParent, hMenu, hInstance, lpParam) > end > def CreateWindowW(lpClassName, lpWindowName, dwStyle, x, y, > nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam) > CreateWindowExW(0,lpClassName, lpWindowName, dwStyle, x, y, nWidth, > nHeight, hWndParent, hMenu, hInstance, lpParam) > end > end > > 3. GetUpdatedClipboardFormats > GetUpdatedClipboardFormats is supported for Vista or later. > Modify windows/clipboard.rb something like this > > begin > API.new(''GetUpdatedClipboardFormats'', ''PIP'', ''I'', ''user32'') > API.new(''AddClipboardFormatListener'', ''L'', ''B'', ''user32'') > API.new(''RemoveClipboardFormatListener'', ''L'', ''B'', ''user32'') > rescue Win32::API::LoadLibraryError > # Windows Vista or later > endMany thanks for this. I''ve made the changes in windows-pr (including the addition of DefProcName in Windows::Window::Message) The only issue I had was that it always returns at least 1 notification when I first run the program, even when the clipboard is clear. I could add an internal counter easily enough and only yield after the 1st notification, but I wanted to make sure there wasn''t a more appropriate solution first. Regards, Dan
Paul Rogers wrote:> I could realy do with a clipboard monitor right now. Is there anything I > can do to help out with this?Thanks Paul. I think we''ll have a new release out within a week that implements this. Regards, Dan
2009/4/24 Daniel Berger <djberg96 at gmail.com>:> > Many thanks for this. I''ve made the changes in windows-pr (including the > addition of DefProcName in Windows::Window::Message) > > The only issue I had was that it always returns at least 1 notification when > I first run the program, even when the clipboard is clear. > > I could add an internal counter easily enough and only yield after the 1st > notification, but I wanted to make sure there wasn''t a more appropriate > solution first. >I guess the first notification is for giving the chance of display the current clipboard content to the new attached clipboard viewer. Thus Initializing flag would be sufficient. Regards, Park Heesob