/*
 * Copyright (c) 2000-2009 TeamDev Ltd. All rights reserved.
 * TeamDev PROPRIETARY and CONFIDENTIAL.
 * Use is subject to license terms.
 */
import com.jniwrapper.win32.Msg;
import com.jniwrapper.win32.Handle;
import com.jniwrapper.win32.ui.*;
import com.jniwrapper.win32.gdi.DC;
import com.jniwrapper.win32.gdi.Brush;
import com.jniwrapper.win32.system.Module;
import com.jniwrapper.Function;
import com.jniwrapper.Bool;
import com.jniwrapper.UInt;

public class ClipboardViewerSample
{
    static final String CLASS_NAME = "JW_ClipboardViewerTest";

    public ClipboardViewerSample()
    {
    }

    static class ClipboardViewerTestWindowProc extends WindowProc
    {
        private long hwndNextViewer;

        public void callback()
        {
            final int msg = (int)_msg.getValue();
            if (msg == Msg.WM_CREATE)
            {
                // Register clipboard viewer
                final Function setClipboardViewer = User32.getInstance().getFunction("SetClipboardViewer");
                final Handle prevWnd = new Handle();
                setClipboardViewer.invoke(prevWnd, new Handle(_wnd.getValue()));
                hwndNextViewer = prevWnd.getValue();
            }
            else if (msg == Msg.WM_DESTROY)
            {
                // Unregister clipboard viewer
                final Function changeClipboardChain = User32.getInstance().getFunction("ChangeClipboardChain");
                changeClipboardChain.invoke(new Bool(), new Handle(_wnd.getValue()), new Handle(hwndNextViewer));
            }
            else if (msg == Msg.WM_CHANGECBCHAIN)
            {                  
                if (_wParam.getValue() == hwndNextViewer)
                {   // If the next window is closing, repair the chain.
                    hwndNextViewer = _lParam.getValue();
                }
                else if (hwndNextViewer != 0)
                {
                    // Otherwise, pass the message to the next link.
                    (new Wnd(hwndNextViewer)).sendMessageEx(msg, _wParam.getValue(), _lParam.getValue());
                }
            }
            else if (msg == Msg.WM_DRAWCLIPBOARD)
            {
                final Function openClipboard = User32.getInstance().getFunction("OpenClipboard");
                final Function closeClipboard = User32.getInstance().getFunction("CloseClipboard");
                final Function enumClipboardFormats = User32.getInstance().getFunction("EnumClipboardFormats");

                System.out.println("Starting to enumerate clipboard formats:");
                openClipboard.invoke(new Bool(), _wnd);
                long formatID = 0;
                do {
                    final UInt res = new UInt();
                    enumClipboardFormats.invoke(res, new UInt(formatID));
                    formatID = res.getValue();
                    if (formatID != 0) {
                        System.out.println("" + formatID);
                    }
                } while (formatID != 0);
                closeClipboard.invoke(new Bool());
                System.out.println("Clipboard formats enumeration done.");

                // Pass the message to the next window in clipboard
                // viewer chain.
                (new Wnd(hwndNextViewer)).sendMessageEx(msg, _wParam.getValue(), _lParam.getValue());
            }
            else if (msg == Msg.WM_PAINT)
            {
                PaintStruct paintStruct = new PaintStruct();
                DC hDC = _wnd.beginPaint(paintStruct);
                hDC.fillRect(_wnd.getClientRect(), Brush.getStockObject(Brush.StockBrush.GRAY_BRUSH));
                _wnd.endPaint(paintStruct);
            }

            super.callback();
        }
    }

    public static void main(String[] args) throws Exception {
        WndClass wndClass = new WndClass(new ClipboardViewerTestWindowProc(), CLASS_NAME);
        wndClass.register();

        Module hModule = Module.getCurrent();
        Handle NULL = new Handle();
        Wnd wnd = Wnd.createWindow(CLASS_NAME, "Clipboard listener",
            Wnd.WS_OVERLAPPEDWINDOW | Wnd.WS_VISIBLE, 0, 0, 100, 100, new Wnd(), NULL, hModule, NULL);

        wnd.show(Wnd.ShowWindowCommand.SHOW);
        wnd.eventLoop();
    }
}