2006年11月06日

システムメニューの改造 & ウィンドウを最前面に表示

参考:
猫でもわかるプログラミング
第12章 システムメニューの改造
http://www.kumei.ne.jp/c_lang/sdk/sdk_12.htm

システムメニューというのは、ウィンドウのタイトルバーのアイコンをクリックしたり、 タスクバーのボタンを右クリックしたときに出てくるメニューらしい。
そのシステムメニューに、「常に最前面に表示」なんて項目があったらいいなと常々思っていたので作ってみる。

ポイント

  1. システムメニューのメニューハンドルを取得 (GetSystemMenu)
  2. システムメニューの項目が選択されたときの処理 (WM_SYSCOMMAND)
  3. ウィンドウを最前面に (SetWindowPos, HWND_TOPMOST)

require 'basewin' # basewin.rb
require 'Win32API'

WM_PAINT                        = 0x000F
WM_SYSCOMMAND                   = 0x0112
DT_WORDBREAK                = 0x00000010

MF_STRING           = 0x00000000
MF_UNCHECKED        = 0x00000000
MF_CHECKED          = 0x00000008
SC_RESTORE      = 0xF120 # 元のサイズに戻す

WS_EX_TOPMOST           = 0x00000008
HWND_TOPMOST    = -1
HWND_NOTOPMOST  = -2
SWP_NOSIZE          = 0x0001
SWP_NOMOVE          = 0x0002

IDSM_TOPMOST = 2001

class MyWindow < BaseWindow
  SetBkMode = Win32API.new('Gdi32', 'SetBkMode', 'II', 'I')
  SetTextColor = Win32API.new('Gdi32', 'SetTextColor', 'II', 'I')
  TRANSPARENT = 1
  
  GetSystemMenu = Win32API.new('User32', 'GetSystemMenu', 'II', 'I')
  InsertMenuA = Win32API.new('User32', 'InsertMenuA', 'IIIIP', 'I')
  AppendMenuA = Win32API.new('User32', 'AppendMenuA', 'IIIP', 'I')
  SetWindowPos = Win32API.new('User32', 'SetWindowPos', 'IIIIIII', 'I')
  CheckMenuItem = Win32API.new('User32', 'CheckMenuItem', 'III', 'I')
  
  def initialize(*arg)
    super
    setHandler(WM_PAINT, method(:on_paint))
    setHandler(WM_SYSCOMMAND, method(:on_syscommand))
  end
  
  def construct
    self.caption = "猫でもわかるプログラミング"
    move(100, 100, 300, 200)
    # システムメニュー
    @sysmenu = GetSystemMenu.call(hWnd, 0);
    InsertMenuA.call(@sysmenu, SC_RESTORE, MF_STRING, IDSM_TOPMOST, '常に最前面に表示(&T)');
  end
  
  def on_paint(msg)
    SetTextColor.call(hdc, RGB(0,0,0xff))
    oldbkmode = SetBkMode.call(hdc, TRANSPARENT)
    x, y, w, h = self.clientrect
    drawText("参考ページ\n猫でもわかるプログラミング!\nです。", 0+30, 0+30, w-30, h-30, nil, DT_WORDBREAK)
    SetBkMode.call(hdc, oldbkmode)
  end
  
  def on_syscommand(msg)
    case msg.wParam
    when IDSM_TOPMOST
      if self.exstyle & WS_EX_TOPMOST == WS_EX_TOPMOST then
        SetWindowPos.call(hWnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE)
        CheckMenuItem.call(@sysmenu, IDSM_TOPMOST, MF_UNCHECKED)
      else
        SetWindowPos.call(hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE)
        CheckMenuItem.call(@sysmenu, IDSM_TOPMOST, MF_CHECKED)
      end
      msg.retval = 0
    end
  end
end

form = MyApp.newwindow(nil, MyWindow)
form.create.show
MyApp.application.messageloop

タグ:ruby swin win32
posted by alexnova at 19:29| Comment(0) | TrackBack(0) | 日記 | このブログの読者になる | 更新情報をチェックする
この記事へのコメント
コメントを書く
お名前:

メールアドレス:

ホームページアドレス:

コメント:

認証コード: [必須入力]


※画像の中の文字を半角で入力してください。
この記事へのトラックバックURL
http://blog.seesaa.jp/tb/26884598

この記事へのトラックバック
×

この広告は1年以上新しい記事の投稿がないブログに表示されております。