HSP | スクロールバーつきウィンドウ | 簡単?

HSP | スクロールバーつきウィンドウ | 簡単?

スクロールバーつきウィンドウを簡単に設置できるかも知れなくするモジュール作りました。
ググってすでに似たようなものを見つけましたが、それより高機能にしました。
・表示したい画像のサイズの指定が可能
・スクロールする幅の指定が可能
・マウスによるスクロールが可能 ([Shift]キー押しながらで横スクロール)
・スクロールバーを右クリックし、「最上部」「最下部」「左の端」「右の端」が使える
「表示したい画像のサイズ」が「ウィンドウ初期化サイズ」で固定ならば、「groll」した場合、スクロールしてからウィンドウサイズを大きくしたとき自動的に右下に合わせて画像移動してくれますが、そうでない場合は自前で処理しなければならないので大変でした…。
また、「WM_MOUSEWHEEL メッセージ」を受け取った時に「oncmd」で「gosub」するようにしているので、システム変数「mousew」が正常動作せず、「wparam」から取得する必要があります。(詳細はプログラムで)
あと、ここでは HSP のプログラムなので、画像表示位置や画像表示サイズを HSP の関数 (「ginfo」) で取得するようにしちゃってますが、本当は「GetScrollBar~」関数でいろいろ取得してやるべきです。

// 
// モジュール
// 

#ifndef __MSCROLLBAR__
#define __MSCROLLBAR__

#include "user32.as"

#module

// 
// ウィンドウにスクロールバー設定
// 
// w, h   : 表示したい画像の X, Y サイズ
// cw, ch : 文字の X, Y サイズ (スクロール用)
// sw, sh : 文字の X, Y 文字数 (スクロール用)
// 
#deffunc ScrollBar int w, int h, int cw, int ch, int sw, int sh

// SCROLLINFO
scrollinfo.0 = 28   /* cbSize    */ // sizeof(scrollinfo)

scrollinfo.1 = 0x1F /* fMask     */ // (SIF_ALL | SIF_DISABLENOSCROLL), (SIF_RANGE | SIF_PAGE | SIF_POS | SIF_DISABLENOSCROLL | SIF_TRACKPOS)
scrollinfo.2 = 0    /* nMin      */
scrollinfo.3 = 0    /* nMax      */
scrollinfo.4 = 0    /* nPage     */
scrollinfo.5 = 0    /* nPos      */
scrollinfo.6 = 0    /* nTrackPos */

// サイズ設定
win(ginfo_sel * 2) = w, h
char(ginfo_sel * 2) = cw, ch
scroll(ginfo_sel * 2) = sw, sh

// 割り込み設定
oncmd gosub *OnSize , 0x0005 // WM_SIZE
oncmd gosub *OnHScroll, 0x0114 // WM_HSCROLL
oncmd gosub *OnVScroll, 0x0115 // WM_VSCROLL
oncmd gosub *OnMouseWheel, 0x020A // WM_MOUSEWHEEL

// ウィンドウスタイル変更
GetWindowLong hwnd, -16                    // GWL_STYLE
SetWindowLong hwnd, -16, stat | 0x00300000 // GWL_STYLE, WS_VSCROLL | WS_HSCROLL

SetWindowPos hwnd, 0, 0, 0, 0, 0, 0x37 // SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED

gsel ginfo_sel, -1 : gsel ginfo_sel, 1

return

// 
// WM_SIZE 発生時
// 
*OnSize

// スクロールバー
repeat 2

; GetSystemMetrics 3 - cnt // (SM_CYHSCROLL, SM_CXVSCROLL)

if (win(ginfo_intid * 2 + cnt) > ginfo(12 + cnt)) { // 描画エリアに入りきっていないとき

// 表示位置更新
if (ginfo(8 + cnt) > win(ginfo_intid * 2 + cnt) - ginfo(12 + cnt)) { // (ginfo_vx, ginfo_vy), (ginfo_winx, ginfo_winy)
switch cnt
case 0
groll win(ginfo_intid * 2 + 0) - ginfo_winx, ginfo_vy
swbreak
case 1
groll ginfo_vx, win(ginfo_intid * 2 + 1) - ginfo_winy
swbreak
swend
}

// スクロールバー更新
scrollinfo.3 = win(ginfo_intid * 2 + cnt) /* nMax  */
scrollinfo.4 = ginfo(12 + cnt)            /* nPage */ // (ginfo_winx, ginfo_winy)
scrollinfo.5 = ginfo(8  + cnt)            /* nPos  */ // (ginfo_vx  , ginfo_vy  )

SetScrollInfo hWnd, cnt, varptr(scrollinfo), 1 // (SB_HORZ, SB_VERT), TRUE

} else { // 描画エリアに入りきっているとき

// 表示位置更新
switch cnt
case 0
groll 0, ginfo_vy
swbreak
case 1
groll ginfo_vx, 0
swbreak
swend

// スクロールバー更新
Sho
wScrollBar hwnd, cnt, 0 // (SB_HORZ, SB_VERT), FALSE

}

loop

return

// 
// WM_HSCROLL 発生時
// 
*OnHScroll
nSBCode = wparam & 0xFFFF
nPos    = wParam >> 16 & 0xffff

// 現在の表示位置取得
curPos = ginfo_vx

// 表示位置変更
switch (nSBCode)
case 0 // SB_LINELEFT
curPos -= char(ginfo_intid * 2 + 0)
swbreak
case 1 // SB_LINERIGHT
curPos += char(ginfo_intid * 2 + 0)
swbreak
case 2 // SB_PAGELEFT
curPos -= char(ginfo_intid * 2 + 0) * scroll(ginfo_intid * 2 + 0)
swbreak
case 3 // SB_PAGERIGHT
curPos += char(ginfo_intid * 2 + 0) * scroll(ginfo_intid * 2 + 0)
swbreak
case 4 // (SB_THUMBPOSITION)
curPos = nPos
swbreak
case 5 // (SB_THUMBTRACK)
curPos = nPos
swbreak
case 6 // SB_LEFT
curPos = 0
swbreak
case 7 // SB_RIGHT
curPos = win(ginfo_intid * 2 + 0) - ginfo_winx
swbreak
case 8 // (SB_ENDSCROLL)

swbreak
swend

// 表示位置を範囲内に
if (curPos < 0) : curPos = 0
if (curPos > win(ginfo_intid * 2 + 0) - ginfo_winx) : curPos = win(ginfo_intid * 2 + 0) - ginfo_winx

// 表示位置更新
groll curPos, ginfo_vy

// スクロールバー更新
SetScrollPos hWnd, 0, curPos, 1

return

// 
// WM_VSCROLL 発生時
// 
*OnVScroll
nSBCode = wparam & 0xFFFF
nPos    = wParam >> 16 & 0xffff

// 現在の表示位置取得
curPos = ginfo_vy

// 表示位置変更
switch (nSBCode)
case 0 // SB_LINEUP
curPos -= char(ginfo_intid * 2 + 1)
swbreak
case 1 // SB_LINEDOWN
curPos += char(ginfo_intid * 2 + 1)
swbreak
case 2 // SB_PAGEUP
curPos -= char(ginfo_intid * 2 + 1) * scroll(ginfo_intid * 2 + 1)
swbreak
case 3 // SB_PAGEDOWN
curPos += char(ginfo_intid * 2 + 1) * scroll(ginfo_intid * 2 + 1)
swbreak
case 4 // (SB_THUMBPOSITION)
curPos = nPos
swbreak
case 5 // (SB_THUMBTRACK)
curPos = nPos
swbreak
case 6 // SB_TOP
curPos = 0
swbreak
case 7 // SB_BOTTOM
curPos = win(ginfo_intid * 2 + 1) - ginfo_winy
swbreak
case 8 // (SB_ENDSCROLL)

swbreak
swend

// 表示位置を範囲内に
if (curPos < 0) : curPos = 0
if (curPos > win(ginfo_intid * 2 + 1) - ginfo_winy) : curPos = win(ginfo_intid * 2 + 1) - ginfo_winy

// 表示位置更新
groll ginfo_vx, curPos

// スクロールバー更新
SetScrollPos hWnd, 1, curPos, 1

return

// 
// WM_MOUSEWHEEL 発生時
// 
*OnMouseWheel
fwKeys = wParam & 0xFFFF
zDelta = wParam >> 16 & 0xffff
// xPos = lParam & 0xFFFF
// yPos = lParam >> 16 & 0xffff

// ・割り込みを奪っているので、mousew が正常に動かない
//  そのため、自前で算出する
// ・ HSP は signed int しか扱えないため、
//  ビット操作を行って signed short を正しい値にする
// ・ 返る値は mousew 同じく 120 の倍数 (WIndows の仕様)
_mousew = (zDelta << 16) >> 16

if (fwKeys == 0x0004) { // MK_SHIFT // 水平方向のスクロール

// 現在の表示位置取得
curPos = ginfo_vx

// 表示位置変更
curPos -= char(ginfo_intid * 2 + 0) * scroll(ginfo_intid * 2 + 0) * (_mousew / 120)

// 表示位置を範囲内に
if (curPos < 0) : curPos = 0
if (curPos > win(ginfo_intid * 2 + 0) - ginfo_winx) : curPos = win(ginfo_intid * 2 + 0) - ginfo_winx

// 表示位置更新
groll curPos, ginfo_vy

// スクロールバー更新
SetScrollPos hWnd, 0, curPos, 1

} else { // 垂直方向のスクロール

// 現在の表示位置取得
curPos = ginfo_vy

// 表示位置変更
curPos -= char(ginfo_intid * 2 + 1) * scroll(ginfo_intid * 2 + 1) * (_mousew / 120)

// 表示位置を範囲内に
if (curPos < 0) : curPos = 0
if (curPos > win(ginfo_intid * 2 + 1) - ginfo_winy) : curPos = win(ginfo_intid * 2 + 1) - ginfo_winy

// 表示位置更新
groll ginfo_vx, curPos

// スクロールバー更新
SetScrollPos hWnd, 1, curPos, 1

}

return

#global

#endif

サンプルはこちら↓
↓ブログランキング投票お願いします~。