WM_SIZE(=$005) は「ウィンドウが変更された後」に呼び出されるメッセージみたいです。
なので、1回はみ出して表示された後、width でリサイズしているのでガクガクした感じになってしまうようですね。
WM_SIZING = 0x0214
WM_SIZINGはサイズ変更中に呼び出されるメッセージで、lparamから得られるRECT構造体(ウィンドウの位置・サイズ)を上書きすることでウィンドウサイズを変更することができるみたいです。
#include "user32.as"
X = 640 : Y = 480
screen 1, ginfo_dispX, ginfo_dispY
width 400,400
GetWindowLong hwnd, -16
SetWindowLong hwnd, -16, ( stat | $00090000 )
oncmd gosub *sub_LIMIT, 0x0214 ;WM_SIZING
stop
*sub_LIMIT
// lparam には RECT 構造体が送られる
dupptr left, lparam, 4
dupptr top, lparam+4, 4
dupptr right, lparam+8, 4
dupptr bottom, lparam+12, 4
// ウィンドウ情報
color 255,255,255 :boxf :pos 0,0
size_x = right-left
size_y = bottom-top
color 255
mes strf("( onX, onY) = (%d,%d)", size_x, size_y)
color
mes strf("(sizeX,sizeY) = (%d,%d)", ginfo_sizex,ginfo_sizeY)
mes strf("( winX, winY) = (%d,%d)", ginfo_winx,ginfo_winY)
v_temp = right-left, bottom-top, 0
if X < v_temp(0) { v_temp(0) = X : v_temp(2)++ }
if Y < v_temp(1) { v_temp(1) = Y : v_temp(2)++ }
if v_temp(2) {
right = left + v_temp(0)
bottom = top + v_temp(1)
}
return
注意点として、WM_SIZING はウィンドウサイズ変更前に呼び出されるので、
size_x(=right-left), size_y(=bottom-top) は変更予定のサイズ、
ginfo_sizex, ginfo_sizeY は現在のサイズ(変更予定の1つ前)
となっていますので注意してください。
【参考】
『WM_SIZE vs WM_SIZING』
https://suzulang.com/wm_size-vs-wm_sizing/
『ウィンドウのサイズ変更を一定の比に保とうとするとビクビクする』
http://hsp.tv/play/pforum.php?mode=pastwch&num=65574