ffi-wingui-core 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License
2
2
 
3
- Copyright (c) 2010 - 2011 Radoslav Peev
3
+ Copyright (c) 2011 Radoslav Peev
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
data/examples/Command.rbw CHANGED
@@ -4,7 +4,7 @@ include WinGUI
4
4
 
5
5
  EnableVisualStyles()
6
6
 
7
- APPNAME = File.basename(__FILE__, '.rbw')
7
+ APPNAME = L(File.basename(__FILE__, '.rbw'))
8
8
 
9
9
  CMD_ITEM1 = WM_APP + 1
10
10
  CTL_BUTTON1 = CMD_ITEM1 + 1
@@ -36,8 +36,8 @@ def onCreate(hwnd,
36
36
 
37
37
  hbar = CreateMenu()
38
38
  hmenu1 = CreatePopupMenu()
39
- AppendMenu(hmenu1, MF_STRING, CMD_ITEM1, "Item&1\tAlt+I")
40
- AppendMenu(hbar, MF_POPUP, hmenu1.to_i, 'Menu&1')
39
+ AppendMenu(hmenu1, MF_STRING, CMD_ITEM1, L("Item&1\tAlt+I"))
40
+ AppendMenu(hbar, MF_POPUP, hmenu1.to_i, L('Menu&1'))
41
41
  SetMenu(hwnd, hbar)
42
42
 
43
43
  accels = [
@@ -59,8 +59,8 @@ def onCreate(hwnd,
59
59
  xtra[:hmf] = CreateFontIndirect(ncm[:lfMenuFont]);
60
60
 
61
61
  hbtn1 = CreateWindowEx(
62
- 0, 'Button', '&Button1', WS_CHILD | WS_VISIBLE,
63
- 10, 10, 100, 25,
62
+ 0, L('Button'), L('&Button1'), WS_CHILD | WS_VISIBLE,
63
+ *DPIScale(10, 10, 100, 25),
64
64
  hwnd, FFI::Pointer.new(CTL_BUTTON1), GetModuleHandle(nil), nil
65
65
  )
66
66
  SendMessage(hbtn1, WM_SETFONT, xtra[:hmf].to_i, 1)
@@ -82,7 +82,7 @@ def onItem1(verb,
82
82
  hctl, hwnd
83
83
  )
84
84
  MessageBox(hwnd,
85
- __method__.to_s,
85
+ L(__method__.to_s),
86
86
  APPNAME,
87
87
  MB_ICONINFORMATION
88
88
  )
@@ -106,7 +106,7 @@ def onButton1(verb,
106
106
  hctl, hwnd
107
107
  )
108
108
  MessageBox(hwnd,
109
- __method__.to_s,
109
+ L(__method__.to_s),
110
110
  APPNAME,
111
111
  MB_ICONINFORMATION
112
112
  )
@@ -125,11 +125,12 @@ def onButton1(verb,
125
125
  0
126
126
  end
127
127
 
128
- def windowProc(hwnd,
129
- uMsg,
130
- wParam, lParam
131
- )
132
- case uMsg
128
+ WindowProc = FFI::Function.new(:long,
129
+ [:pointer, :uint, :uint, :long],
130
+ convention: :stdcall
131
+ ) { |hwnd, uMsg, wParam, lParam|
132
+ begin
133
+ result = case uMsg
133
134
  when WM_NCCREATE
134
135
  DefWindowProc(hwnd, uMsg, wParam, lParam)
135
136
 
@@ -138,47 +139,46 @@ def windowProc(hwnd,
138
139
  CREATESTRUCT.new(FFI::Pointer.new(lParam))[:lpCreateParams].to_i
139
140
  )
140
141
 
141
- return 1
142
+ 1
142
143
  when WM_CREATE
143
- return onCreate(hwnd, CREATESTRUCT.new(FFI::Pointer.new(lParam)))
144
+ onCreate(hwnd, CREATESTRUCT.new(FFI::Pointer.new(lParam)))
144
145
  when WM_DESTROY
145
- return onDestroy(hwnd)
146
+ onDestroy(hwnd)
146
147
  when WM_COMMAND
147
148
  id, verb = LOWORD(wParam), HIWORD(wParam)
148
149
  hctl = FFI::Pointer.new(lParam)
149
150
 
150
151
  case id
151
152
  when CMD_ITEM1
152
- return onItem1(verb, hctl, hwnd)
153
+ onItem1(verb, hctl, hwnd)
153
154
  when CTL_BUTTON1
154
- return onButton1(verb, hctl, hwnd)
155
+ onButton1(verb, hctl, hwnd)
155
156
  end
156
157
  end
157
158
 
158
- DefWindowProc(hwnd, uMsg, wParam, lParam)
159
+ result || DefWindowProc(hwnd, uMsg, wParam, lParam)
159
160
  rescue
160
161
  MessageBox(nil,
161
- %'#{$!.to_s}\n\n#{$!.backtrace.join("\n")}',
162
+ L(%'#{$!.to_s}\n\n#{$!.backtrace.join("\n")}'),
162
163
  APPNAME,
163
164
  MB_ICONERROR
164
165
  ); PostQuitMessage(2)
165
166
  end
167
+ }
166
168
 
167
169
  def main
168
170
  wc = WNDCLASSEX.new
169
171
  xtra = WndExtra.new
170
172
 
171
173
  wc[:cbSize] = wc.size
172
- wc[:lpfnWndProc] = method(:windowProc)
174
+ wc[:lpfnWndProc] = WindowProc
173
175
  #wc[:cbWndExtra] = FFI::Pointer.size
174
176
  wc[:cbWndExtra] = FFI::Type::Builtin::POINTER.size
175
177
  wc[:hInstance] = GetModuleHandle(nil)
176
178
  wc[:hIcon] = LoadIcon(nil, IDI_APPLICATION)
177
179
  wc[:hCursor] = LoadCursor(nil, IDC_ARROW)
178
180
  wc[:hbrBackground] = FFI::Pointer.new(CTLCOLOR_DLG + 1)
179
- wc[:lpszClassName] = className = FFI::MemoryPointer.from_string(
180
- APPNAME
181
- )
181
+ wc[:lpszClassName] = className = PWSTR(APPNAME)
182
182
 
183
183
  DetonateLastError(0, :RegisterClassEx,
184
184
  wc
@@ -210,7 +210,7 @@ def main
210
210
  exit(msg[:wParam])
211
211
  rescue
212
212
  MessageBox(nil,
213
- %'#{$!.to_s}\n\n#{$!.backtrace.join("\n")}',
213
+ L(%'#{$!.to_s}\n\n#{$!.backtrace.join("\n")}'),
214
214
  APPNAME,
215
215
  MB_ICONERROR
216
216
  ); exit(1)
data/examples/Hello.rbw CHANGED
@@ -5,7 +5,7 @@ include WinGUI
5
5
  EnableVisualStyles()
6
6
 
7
7
  MessageBox(nil,
8
- 'Hello, world!',
9
- 'Hello',
8
+ L('Hello, world!'),
9
+ L('Hello'),
10
10
  MB_ICONINFORMATION
11
11
  )
@@ -4,14 +4,14 @@ include WinGUI
4
4
 
5
5
  EnableVisualStyles()
6
6
 
7
- APPNAME = File.basename(__FILE__, '.rbw')
7
+ APPNAME = L(File.basename(__FILE__, '.rbw'))
8
8
 
9
9
  def onCreate(hwnd,
10
10
  cs
11
11
  )
12
12
  answer = MessageBox(nil,
13
- 'Create?',
14
- cs[:lpszName].read_string,
13
+ L('Create?'),
14
+ cs[:lpszName],
15
15
  MB_YESNO | MB_ICONQUESTION
16
16
  )
17
17
 
@@ -22,7 +22,7 @@ end
22
22
 
23
23
  def onClose(hwnd)
24
24
  answer = MessageBox(hwnd,
25
- 'Close?',
25
+ L('Close?'),
26
26
  APPNAME,
27
27
  MB_YESNO | MB_ICONQUESTION |
28
28
  MB_DEFBUTTON2
@@ -35,7 +35,7 @@ end
35
35
 
36
36
  def onDestroy(hwnd)
37
37
  MessageBox(nil,
38
- __method__.to_s,
38
+ L(__method__.to_s),
39
39
  APPNAME,
40
40
  MB_ICONINFORMATION
41
41
  )
@@ -43,40 +43,40 @@ def onDestroy(hwnd)
43
43
  PostQuitMessage(0); 0
44
44
  end
45
45
 
46
- def windowProc(hwnd,
47
- uMsg,
48
- wParam, lParam
49
- )
50
- case uMsg
46
+ WindowProc = FFI::Function.new(:long,
47
+ [:pointer, :uint, :uint, :long],
48
+ convention: :stdcall
49
+ ) { |hwnd, uMsg, wParam, lParam|
50
+ begin
51
+ result = case uMsg
51
52
  when WM_CREATE
52
- return onCreate(hwnd, CREATESTRUCT.new(FFI::Pointer.new(lParam)))
53
+ onCreate(hwnd, CREATESTRUCT.new(FFI::Pointer.new(lParam)))
53
54
  when WM_CLOSE
54
- return onClose(hwnd)
55
+ onClose(hwnd)
55
56
  when WM_DESTROY
56
- return onDestroy(hwnd)
57
+ onDestroy(hwnd)
57
58
  end
58
59
 
59
- DefWindowProc(hwnd, uMsg, wParam, lParam)
60
+ result || DefWindowProc(hwnd, uMsg, wParam, lParam)
60
61
  rescue
61
62
  MessageBox(nil,
62
- %'#{$!.to_s}\n\n#{$!.backtrace.join("\n")}',
63
+ L(%'#{$!.to_s}\n\n#{$!.backtrace.join("\n")}'),
63
64
  APPNAME,
64
65
  MB_ICONERROR
65
66
  ); PostQuitMessage(2)
66
67
  end
68
+ }
67
69
 
68
70
  def main
69
71
  wc = WNDCLASSEX.new
70
72
 
71
73
  wc[:cbSize] = wc.size
72
- wc[:lpfnWndProc] = method(:windowProc)
74
+ wc[:lpfnWndProc] = WindowProc
73
75
  wc[:hInstance] = GetModuleHandle(nil)
74
76
  wc[:hIcon] = LoadIcon(nil, IDI_APPLICATION)
75
77
  wc[:hCursor] = LoadCursor(nil, IDC_ARROW)
76
78
  wc[:hbrBackground] = FFI::Pointer.new(COLOR_WINDOW + 1)
77
- wc[:lpszClassName] = className = FFI::MemoryPointer.from_string(
78
- APPNAME
79
- )
79
+ wc[:lpszClassName] = className = PWSTR(APPNAME)
80
80
 
81
81
  DetonateLastError(0, :RegisterClassEx,
82
82
  wc
@@ -106,7 +106,7 @@ def main
106
106
  exit(msg[:wParam])
107
107
  rescue
108
108
  MessageBox(nil,
109
- %'#{$!.to_s}\n\n#{$!.backtrace.join("\n")}',
109
+ L(%'#{$!.to_s}\n\n#{$!.backtrace.join("\n")}'),
110
110
  APPNAME,
111
111
  MB_ICONERROR
112
112
  ); exit(1)
@@ -4,14 +4,14 @@ include WinGUI
4
4
 
5
5
  EnableVisualStyles()
6
6
 
7
- APPNAME = File.basename(__FILE__, '.rbw')
7
+ APPNAME = L(File.basename(__FILE__, '.rbw'))
8
8
 
9
9
  def onNCCreate(hwnd,
10
10
  cs
11
11
  )
12
12
  answer = MessageBox(nil,
13
- 'NCCreate?',
14
- cs[:lpszName].read_string,
13
+ L('NCCreate?'),
14
+ cs[:lpszName],
15
15
  MB_YESNO | MB_ICONQUESTION
16
16
  )
17
17
 
@@ -24,8 +24,8 @@ def onCreate(hwnd,
24
24
  cs
25
25
  )
26
26
  answer = MessageBox(nil,
27
- 'Create?',
28
- cs[:lpszName].read_string,
27
+ L('Create?'),
28
+ cs[:lpszName],
29
29
  MB_YESNO | MB_ICONQUESTION
30
30
  )
31
31
 
@@ -36,7 +36,7 @@ end
36
36
 
37
37
  def onClose(hwnd)
38
38
  answer = MessageBox(hwnd,
39
- 'Close?',
39
+ L('Close?'),
40
40
  APPNAME,
41
41
  MB_YESNO | MB_ICONQUESTION |
42
42
  MB_DEFBUTTON2
@@ -49,7 +49,7 @@ end
49
49
 
50
50
  def onDestroy(hwnd)
51
51
  MessageBox(nil,
52
- __method__.to_s,
52
+ L(__method__.to_s),
53
53
  APPNAME,
54
54
  MB_ICONINFORMATION
55
55
  )
@@ -59,7 +59,7 @@ end
59
59
 
60
60
  def onNCDestroy(hwnd)
61
61
  MessageBox(nil,
62
- __method__.to_s,
62
+ L(__method__.to_s),
63
63
  APPNAME,
64
64
  MB_ICONINFORMATION
65
65
  )
@@ -67,46 +67,46 @@ def onNCDestroy(hwnd)
67
67
  PostQuitMessage(0); 0
68
68
  end
69
69
 
70
- def windowProc(hwnd,
71
- uMsg,
72
- wParam, lParam
73
- )
74
- case uMsg
70
+ WindowProc = FFI::Function.new(:long,
71
+ [:pointer, :uint, :uint, :long],
72
+ convention: :stdcall
73
+ ) { |hwnd, uMsg, wParam, lParam|
74
+ begin
75
+ result = case uMsg
75
76
  when WM_NCCREATE
76
77
  DefWindowProc(hwnd, uMsg, wParam, lParam)
77
78
 
78
- return onNCCreate(hwnd, CREATESTRUCT.new(FFI::Pointer.new(lParam)))
79
+ onNCCreate(hwnd, CREATESTRUCT.new(FFI::Pointer.new(lParam)))
79
80
  when WM_CREATE
80
- return onCreate(hwnd, CREATESTRUCT.new(FFI::Pointer.new(lParam)))
81
+ onCreate(hwnd, CREATESTRUCT.new(FFI::Pointer.new(lParam)))
81
82
  when WM_CLOSE
82
- return onClose(hwnd)
83
+ onClose(hwnd)
83
84
  when WM_DESTROY
84
- return onDestroy(hwnd)
85
+ onDestroy(hwnd)
85
86
  when WM_NCDESTROY
86
- return onNCDestroy(hwnd)
87
+ onNCDestroy(hwnd)
87
88
  end
88
89
 
89
- DefWindowProc(hwnd, uMsg, wParam, lParam)
90
+ result || DefWindowProc(hwnd, uMsg, wParam, lParam)
90
91
  rescue
91
92
  MessageBox(nil,
92
- %'#{$!.to_s}\n\n#{$!.backtrace.join("\n")}',
93
+ L(%'#{$!.to_s}\n\n#{$!.backtrace.join("\n")}'),
93
94
  APPNAME,
94
95
  MB_ICONERROR
95
96
  ); PostQuitMessage(2)
96
97
  end
98
+ }
97
99
 
98
100
  def main
99
101
  wc = WNDCLASSEX.new
100
102
 
101
103
  wc[:cbSize] = wc.size
102
- wc[:lpfnWndProc] = method(:windowProc)
104
+ wc[:lpfnWndProc] = WindowProc
103
105
  wc[:hInstance] = GetModuleHandle(nil)
104
106
  wc[:hIcon] = LoadIcon(nil, IDI_APPLICATION)
105
107
  wc[:hCursor] = LoadCursor(nil, IDC_ARROW)
106
108
  wc[:hbrBackground] = FFI::Pointer.new(COLOR_WINDOW + 1)
107
- wc[:lpszClassName] = className = FFI::MemoryPointer.from_string(
108
- APPNAME
109
- )
109
+ wc[:lpszClassName] = className = PWSTR(APPNAME)
110
110
 
111
111
  DetonateLastError(0, :RegisterClassEx,
112
112
  wc
@@ -136,7 +136,7 @@ def main
136
136
  exit(msg[:wParam])
137
137
  rescue
138
138
  MessageBox(nil,
139
- %'#{$!.to_s}\n\n#{$!.backtrace.join("\n")}',
139
+ L(%'#{$!.to_s}\n\n#{$!.backtrace.join("\n")}'),
140
140
  APPNAME,
141
141
  MB_ICONERROR
142
142
  ); exit(1)
data/examples/Minimal.rbw CHANGED
@@ -4,42 +4,42 @@ include WinGUI
4
4
 
5
5
  EnableVisualStyles()
6
6
 
7
- APPNAME = File.basename(__FILE__, '.rbw')
7
+ APPNAME = L(File.basename(__FILE__, '.rbw'))
8
8
 
9
9
  def onDestroy(hwnd)
10
10
  PostQuitMessage(0); 0
11
11
  end
12
12
 
13
- def windowProc(hwnd,
14
- uMsg,
15
- wParam, lParam
16
- )
17
- case uMsg
13
+ WindowProc = FFI::Function.new(:long,
14
+ [:pointer, :uint, :uint, :long],
15
+ convention: :stdcall
16
+ ) { |hwnd, uMsg, wParam, lParam|
17
+ begin
18
+ result = case uMsg
18
19
  when WM_DESTROY
19
- return onDestroy(hwnd)
20
+ onDestroy(hwnd)
20
21
  end
21
22
 
22
- DefWindowProc(hwnd, uMsg, wParam, lParam)
23
+ result || DefWindowProc(hwnd, uMsg, wParam, lParam)
23
24
  rescue
24
25
  MessageBox(nil,
25
- %'#{$!.to_s}\n\n#{$!.backtrace.join("\n")}',
26
+ L(%'#{$!.to_s}\n\n#{$!.backtrace.join("\n")}'),
26
27
  APPNAME,
27
28
  MB_ICONERROR
28
29
  ); PostQuitMessage(2)
29
30
  end
31
+ }
30
32
 
31
33
  def main
32
34
  wc = WNDCLASSEX.new
33
35
 
34
36
  wc[:cbSize] = wc.size
35
- wc[:lpfnWndProc] = method(:windowProc)
37
+ wc[:lpfnWndProc] = WindowProc
36
38
  wc[:hInstance] = GetModuleHandle(nil)
37
39
  wc[:hIcon] = LoadIcon(nil, IDI_APPLICATION)
38
40
  wc[:hCursor] = LoadCursor(nil, IDC_ARROW)
39
41
  wc[:hbrBackground] = FFI::Pointer.new(COLOR_WINDOW + 1)
40
- wc[:lpszClassName] = className = FFI::MemoryPointer.from_string(
41
- APPNAME
42
- )
42
+ wc[:lpszClassName] = className = PWSTR(APPNAME)
43
43
 
44
44
  DetonateLastError(0, :RegisterClassEx,
45
45
  wc
@@ -69,7 +69,7 @@ def main
69
69
  exit(msg[:wParam])
70
70
  rescue
71
71
  MessageBox(nil,
72
- %'#{$!.to_s}\n\n#{$!.backtrace.join("\n")}',
72
+ L(%'#{$!.to_s}\n\n#{$!.backtrace.join("\n")}'),
73
73
  APPNAME,
74
74
  MB_ICONERROR
75
75
  ); exit(1)
@@ -4,7 +4,7 @@ include WinGUI
4
4
 
5
5
  EnableVisualStyles()
6
6
 
7
- APPNAME = File.basename(__FILE__, '.rbw')
7
+ APPNAME = L(File.basename(__FILE__, '.rbw'))
8
8
 
9
9
  WndExtra = Struct.new(
10
10
  :foo
@@ -30,7 +30,7 @@ def onCreate(hwnd,
30
30
  #xtra = ObjectSpace._id2ref(GetWindowLong(hwnd, GWL_USERDATA))
31
31
  xtra = WndExtra::REFS[GetWindowLong(hwnd, GWL_USERDATA)]
32
32
 
33
- xtra[:foo] = 'Foo'
33
+ xtra[:foo] = L('Foo')
34
34
 
35
35
  -1
36
36
  end
@@ -48,11 +48,12 @@ def onDestroy(hwnd)
48
48
  PostQuitMessage(0); 0
49
49
  end
50
50
 
51
- def windowProc(hwnd,
52
- uMsg,
53
- wParam, lParam
54
- )
55
- case uMsg
51
+ WindowProc = FFI::Function.new(:long,
52
+ [:pointer, :uint, :uint, :long],
53
+ convention: :stdcall
54
+ ) { |hwnd, uMsg, wParam, lParam|
55
+ begin
56
+ result = case uMsg
56
57
  when WM_NCCREATE
57
58
  DefWindowProc(hwnd, uMsg, wParam, lParam)
58
59
 
@@ -61,37 +62,36 @@ def windowProc(hwnd,
61
62
  CREATESTRUCT.new(FFI::Pointer.new(lParam))[:lpCreateParams].to_i
62
63
  )
63
64
 
64
- return 1
65
+ 1
65
66
  when WM_CREATE
66
- return onCreate(hwnd, CREATESTRUCT.new(FFI::Pointer.new(lParam)))
67
+ onCreate(hwnd, CREATESTRUCT.new(FFI::Pointer.new(lParam)))
67
68
  when WM_DESTROY
68
- return onDestroy(hwnd)
69
+ onDestroy(hwnd)
69
70
  end
70
71
 
71
- DefWindowProc(hwnd, uMsg, wParam, lParam)
72
+ result || DefWindowProc(hwnd, uMsg, wParam, lParam)
72
73
  rescue
73
74
  MessageBox(nil,
74
- %'#{$!.to_s}\n\n#{$!.backtrace.join("\n")}',
75
+ L(%'#{$!.to_s}\n\n#{$!.backtrace.join("\n")}'),
75
76
  APPNAME,
76
77
  MB_ICONERROR
77
78
  ); PostQuitMessage(2)
78
79
  end
80
+ }
79
81
 
80
82
  def main
81
83
  wc = WNDCLASSEX.new
82
84
  xtra = WndExtra.new
83
85
 
84
86
  wc[:cbSize] = wc.size
85
- wc[:lpfnWndProc] = method(:windowProc)
87
+ wc[:lpfnWndProc] = WindowProc
86
88
  #wc[:cbWndExtra] = FFI::Pointer.size
87
89
  wc[:cbWndExtra] = FFI::Type::Builtin::POINTER.size
88
90
  wc[:hInstance] = GetModuleHandle(nil)
89
91
  wc[:hIcon] = LoadIcon(nil, IDI_APPLICATION)
90
92
  wc[:hCursor] = LoadCursor(nil, IDC_ARROW)
91
93
  wc[:hbrBackground] = FFI::Pointer.new(COLOR_WINDOW + 1)
92
- wc[:lpszClassName] = className = FFI::MemoryPointer.from_string(
93
- APPNAME
94
- )
94
+ wc[:lpszClassName] = className = PWSTR(APPNAME)
95
95
 
96
96
  DetonateLastError(0, :RegisterClassEx,
97
97
  wc
@@ -121,7 +121,7 @@ def main
121
121
  exit(msg[:wParam])
122
122
  rescue
123
123
  MessageBox(nil,
124
- %'#{$!.to_s}\n\n#{$!.backtrace.join("\n")}',
124
+ L(%'#{$!.to_s}\n\n#{$!.backtrace.join("\n")}'),
125
125
  APPNAME,
126
126
  MB_ICONERROR
127
127
  ); exit(1)
@@ -33,16 +33,57 @@ module WinGUI
33
33
  :MAKEWORD, :LOBYTE, :HIBYTE,
34
34
  :MAKELONG, :LOWORD, :HIWORD
35
35
 
36
+ def L(s)
37
+ (s << "\0").encode!('utf-16le')
38
+ end
39
+
40
+ def PWSTR(ws)
41
+ raise 'Invalid Unicode string' unless
42
+ ws.encoding == Encoding::UTF_16LE &&
43
+ ws[-1] == L('')
44
+
45
+ p = FFI::MemoryPointer.new(:ushort, ws.length).
46
+ put_bytes(0, ws)
47
+
48
+ return p unless block_given?
49
+
50
+ begin yield p ensure p.free end
51
+
52
+ nil
53
+ end
54
+
55
+ module_function :L, :PWSTR
56
+
36
57
  class POINT < FFI::Struct
37
58
  layout \
38
59
  :x, :long,
39
60
  :y, :long
61
+
62
+ def self.[](x, y)
63
+ new.tap { |point|
64
+ point[:x], point[:y] = x, y
65
+ }
66
+ end
67
+
68
+ def to_a
69
+ [self[:x], self[:y]]
70
+ end
40
71
  end
41
72
 
42
73
  class SIZE < FFI::Struct
43
74
  layout \
44
75
  :cx, :long,
45
76
  :cy, :long
77
+
78
+ def self.[](cx, cy)
79
+ new.tap { |size|
80
+ size[:cx], size[:cy] = cx, cy
81
+ }
82
+ end
83
+
84
+ def to_a
85
+ [self[:cx], self[:cy]]
86
+ end
46
87
  end
47
88
 
48
89
  class RECT < FFI::Struct
@@ -51,6 +92,16 @@ module WinGUI
51
92
  :top, :long,
52
93
  :right, :long,
53
94
  :bottom, :long
95
+
96
+ def self.[](l, t, r, b)
97
+ new.tap { |rect|
98
+ rect[:left], rect[:top], rect[:right], rect[:bottom] = l, t, r, b
99
+ }
100
+ end
101
+
102
+ def to_a
103
+ [self[:left], self[:top], self[:right], self[:bottom]]
104
+ end
54
105
  end
55
106
 
56
107
  ffi_lib 'kernel32'
@@ -91,7 +142,7 @@ module WinGUI
91
142
  :dwMinorVersion, :ulong,
92
143
  :dwBuildNumber, :ulong,
93
144
  :dwPlatformId, :ulong,
94
- :szCSDVersion, [:char, 128],
145
+ :szCSDVersion, [:ushort, 128],
95
146
  :wServicePackMajor, :ushort,
96
147
  :wServicePackMinor, :ushort,
97
148
  :wSuiteMask, :ushort,
@@ -99,7 +150,7 @@ module WinGUI
99
150
  :wReserved, :uchar
100
151
  end
101
152
 
102
- attach_function :GetVersionEx, :GetVersionExA, [
153
+ attach_function :GetVersionEx, :GetVersionExW, [
103
154
  :pointer
104
155
  ], :int
105
156
 
@@ -163,12 +214,12 @@ module WinGUI
163
214
 
164
215
  WINVER = HIWORD(NTDDI_VERSION)
165
216
 
166
- attach_function :GetModuleHandle, :GetModuleHandleA, [
167
- :string
217
+ attach_function :GetModuleHandle, :GetModuleHandleW, [
218
+ :buffer_in
168
219
  ], :pointer
169
220
 
170
- attach_function :LoadLibrary, :LoadLibraryA, [
171
- :string
221
+ attach_function :LoadLibrary, :LoadLibraryW, [
222
+ :buffer_in
172
223
  ], :pointer
173
224
 
174
225
  attach_function :FreeLibrary, [
@@ -189,7 +240,7 @@ module WinGUI
189
240
  :hModule, :pointer
190
241
  end
191
242
 
192
- attach_function :CreateActCtx, :CreateActCtxA, [
243
+ attach_function :CreateActCtx, :CreateActCtxW, [
193
244
  :pointer
194
245
  ], :pointer
195
246
 
@@ -255,9 +306,7 @@ module WinGUI
255
306
  ac = ACTCTX.new
256
307
 
257
308
  ac[:cbSize] = ac.size
258
- ac[:lpSource] = source = FFI::MemoryPointer.from_string(
259
- File.expand_path(manifest)
260
- )
309
+ ac[:lpSource] = source = PWSTR(L(manifest))
261
310
 
262
311
  COMMON_CONTROLS_ACTCTX[:handle] =
263
312
  DetonateLastError(INVALID_HANDLE_VALUE, :CreateActCtx,
@@ -278,6 +327,12 @@ module WinGUI
278
327
 
279
328
  module_function :EnableVisualStyles
280
329
 
330
+ attach_function :MulDiv, [
331
+ :int,
332
+ :int,
333
+ :int
334
+ ], :int
335
+
281
336
  ffi_lib 'gdi32'
282
337
  ffi_convention :stdcall
283
338
 
@@ -300,6 +355,14 @@ module WinGUI
300
355
  module_function \
301
356
  :RGB, :GetRValue, :GetGValue, :GetBValue
302
357
 
358
+ LOGPIXELSX = 88
359
+ LOGPIXELSY = 90
360
+
361
+ attach_function :GetDeviceCaps, [
362
+ :pointer,
363
+ :int
364
+ ], :int
365
+
303
366
  class LOGFONT < FFI::Struct
304
367
  layout \
305
368
  :lfHeight, :long,
@@ -315,10 +378,10 @@ module WinGUI
315
378
  :lfClipPrecision, :uchar,
316
379
  :lfQuality, :uchar,
317
380
  :lfPitchAndFamily, :uchar,
318
- :lfFaceName, [:char, 32]
381
+ :lfFaceName, [:ushort, 32]
319
382
  end
320
383
 
321
- attach_function :CreateFontIndirect, :CreateFontIndirectA, [
384
+ attach_function :CreateFontIndirect, :CreateFontIndirectW, [
322
385
  :pointer
323
386
  ], :pointer
324
387
 
@@ -365,6 +428,16 @@ module WinGUI
365
428
  ffi_lib 'user32'
366
429
  ffi_convention :stdcall
367
430
 
431
+ if WINVER >= WINVISTA
432
+ attach_function :SetProcessDPIAware, [
433
+
434
+ ], :int
435
+
436
+ Detonate(0, :SetProcessDPIAware) unless
437
+ Object.const_defined?(:DPI_AWARE) &&
438
+ !DPI_AWARE
439
+ end
440
+
368
441
  #{ MB_xxx
369
442
  MB_OK = 0x00000000
370
443
  MB_OKCANCEL = 0x00000001
@@ -402,10 +475,10 @@ module WinGUI
402
475
  IDCONTINUE = 11
403
476
  #}
404
477
 
405
- attach_function :MessageBox, :MessageBoxA, [
478
+ attach_function :MessageBox, :MessageBoxW, [
406
479
  :pointer,
407
- :string,
408
- :string,
480
+ :buffer_in,
481
+ :buffer_in,
409
482
  :uint
410
483
  ], :int
411
484
 
@@ -430,7 +503,7 @@ module WinGUI
430
503
  :long
431
504
  ], :long
432
505
 
433
- attach_function :DefWindowProc, :DefWindowProcA, [
506
+ attach_function :DefWindowProc, :DefWindowProcW, [
434
507
  :pointer,
435
508
  :uint,
436
509
  :uint,
@@ -441,7 +514,7 @@ module WinGUI
441
514
  IDI_APPLICATION = FFI::Pointer.new(32512)
442
515
  #}
443
516
 
444
- attach_function :LoadIcon, :LoadIconA, [
517
+ attach_function :LoadIcon, :LoadIconW, [
445
518
  :pointer,
446
519
  :pointer
447
520
  ], :pointer
@@ -458,7 +531,7 @@ module WinGUI
458
531
  IDC_SIZENESW = FFI::Pointer.new(32643)
459
532
  #}
460
533
 
461
- attach_function :LoadCursor, :LoadCursorA, [
534
+ attach_function :LoadCursor, :LoadCursorW, [
462
535
  :pointer,
463
536
  :pointer
464
537
  ], :pointer
@@ -486,16 +559,16 @@ module WinGUI
486
559
  :hIconSm, :pointer
487
560
  end
488
561
 
489
- attach_function :RegisterClassEx, :RegisterClassExA, [
562
+ attach_function :RegisterClassEx, :RegisterClassExW, [
490
563
  :pointer
491
564
  ], :ushort
492
565
 
493
- attach_function :UnregisterClass, :UnregisterClassA, [
566
+ attach_function :UnregisterClass, :UnregisterClassW, [
494
567
  :pointer,
495
568
  :pointer
496
569
  ], :int
497
570
 
498
- attach_function :GetClassInfoEx, :GetClassInfoExA, [
571
+ attach_function :GetClassInfoEx, :GetClassInfoExW, [
499
572
  :pointer,
500
573
  :pointer,
501
574
  :pointer
@@ -542,10 +615,10 @@ module WinGUI
542
615
  HWND_MESSAGE = FFI::Pointer.new(-3)
543
616
  #}
544
617
 
545
- attach_function :CreateWindowEx, :CreateWindowExA, [
618
+ attach_function :CreateWindowEx, :CreateWindowExW, [
546
619
  :ulong,
547
- :string,
548
- :string,
620
+ :buffer_in,
621
+ :buffer_in,
549
622
  :ulong,
550
623
  :int,
551
624
  :int,
@@ -575,18 +648,18 @@ module WinGUI
575
648
  GCW_ATOM = -32
576
649
  #}
577
650
 
578
- attach_function :SetClassLong, :SetClassLongA, [
651
+ attach_function :SetClassLong, :SetClassLongW, [
579
652
  :pointer,
580
653
  :int,
581
654
  :long
582
655
  ], :ulong
583
656
 
584
- attach_function :GetClassLong, :GetClassLongA, [
657
+ attach_function :GetClassLong, :GetClassLongW, [
585
658
  :pointer,
586
659
  :int
587
660
  ], :ulong
588
661
 
589
- attach_function :GetClassName, :GetClassNameA, [
662
+ attach_function :GetClassName, :GetClassNameW, [
590
663
  :pointer,
591
664
  :pointer,
592
665
  :int
@@ -602,13 +675,13 @@ module WinGUI
602
675
  GWL_WNDPROC = -4
603
676
  #}
604
677
 
605
- attach_function :SetWindowLong, :SetWindowLongA, [
678
+ attach_function :SetWindowLong, :SetWindowLongW, [
606
679
  :pointer,
607
680
  :int,
608
681
  :long
609
682
  ], :long
610
683
 
611
- attach_function :GetWindowLong, :GetWindowLongA, [
684
+ attach_function :GetWindowLong, :GetWindowLongW, [
612
685
  :pointer,
613
686
  :int
614
687
  ], :long
@@ -731,6 +804,48 @@ module WinGUI
731
804
  :pointer
732
805
  ], :int
733
806
 
807
+ attach_function :GetDC, [
808
+ :pointer
809
+ ], :pointer
810
+
811
+ attach_function :ReleaseDC, [
812
+ :pointer,
813
+ :pointer
814
+ ], :int
815
+
816
+ Detonate(FFI::Pointer::NULL, :GetDC,
817
+ nil
818
+ ).tap { |hdc|
819
+ DPIX = GetDeviceCaps(hdc, LOGPIXELSX)
820
+ DPIY = GetDeviceCaps(hdc, LOGPIXELSY)
821
+
822
+ ReleaseDC(nil, hdc)
823
+ }
824
+
825
+ def DPIScaleX(x)
826
+ MulDiv(x, DPIX, 96)
827
+ end
828
+
829
+ def DPIScaleY(y)
830
+ MulDiv(y, DPIY, 96)
831
+ end
832
+
833
+ def DPIScale(*args)
834
+ case args.length
835
+ when 2 # POINT, SIZE
836
+ [DPIScaleX(args[0]), DPIScaleY(args[1])]
837
+ when 4 # RECT
838
+ [
839
+ DPIScaleX(args[0]), DPIScaleY(args[1]),
840
+ DPIScaleX(args[2]), DPIScaleY(args[3])
841
+ ]
842
+ else
843
+ raise ArgumentError
844
+ end
845
+ end
846
+
847
+ module_function :DPIScaleX, :DPIScaleY, :DPIScale
848
+
734
849
  class PAINTSTRUCT < FFI::Struct
735
850
  layout \
736
851
  :hdc, :pointer,
@@ -828,14 +943,14 @@ module WinGUI
828
943
  WM_APP = 0x8000
829
944
  #}
830
945
 
831
- attach_function :SendMessage, :SendMessageA, [
946
+ attach_function :SendMessage, :SendMessageW, [
832
947
  :pointer,
833
948
  :uint,
834
949
  :uint,
835
950
  :long
836
951
  ], :long
837
952
 
838
- attach_function :PostMessage, :PostMessageA, [
953
+ attach_function :PostMessage, :PostMessageW, [
839
954
  :pointer,
840
955
  :uint,
841
956
  :uint,
@@ -852,7 +967,7 @@ module WinGUI
852
967
  :pt, POINT
853
968
  end
854
969
 
855
- attach_function :GetMessage, :GetMessageA, [
970
+ attach_function :GetMessage, :GetMessageW, [
856
971
  :pointer,
857
972
  :pointer,
858
973
  :uint,
@@ -864,7 +979,7 @@ module WinGUI
864
979
  :pointer
865
980
  ], :int
866
981
 
867
- attach_function :TranslateAccelerator, :TranslateAcceleratorA, [
982
+ attach_function :TranslateAccelerator, :TranslateAcceleratorW, [
868
983
  :pointer,
869
984
  :pointer,
870
985
  :pointer
@@ -874,7 +989,7 @@ module WinGUI
874
989
  :pointer
875
990
  ], :int
876
991
 
877
- attach_function :DispatchMessage, :DispatchMessageA, [
992
+ attach_function :DispatchMessage, :DispatchMessageW, [
878
993
  :pointer
879
994
  ], :long
880
995
 
@@ -913,11 +1028,11 @@ module WinGUI
913
1028
  MF_UNHILITE = 0x00000000
914
1029
  #}
915
1030
 
916
- attach_function :AppendMenu, :AppendMenuA, [
1031
+ attach_function :AppendMenu, :AppendMenuW, [
917
1032
  :pointer,
918
1033
  :uint,
919
1034
  :uint,
920
- :string
1035
+ :buffer_in
921
1036
  ], :int
922
1037
 
923
1038
  #{ MF_xxx
@@ -972,7 +1087,7 @@ module WinGUI
972
1087
  :cmd, :ushort
973
1088
  end
974
1089
 
975
- attach_function :CreateAcceleratorTable, :CreateAcceleratorTableA, [
1090
+ attach_function :CreateAcceleratorTable, :CreateAcceleratorTableW, [
976
1091
  :pointer,
977
1092
  :int
978
1093
  ], :pointer
@@ -1010,7 +1125,7 @@ module WinGUI
1010
1125
  SPI_GETNONCLIENTMETRICS = 0x0029
1011
1126
  #}
1012
1127
 
1013
- attach_function :SystemParametersInfo, :SystemParametersInfoA, [
1128
+ attach_function :SystemParametersInfo, :SystemParametersInfoW, [
1014
1129
  :uint,
1015
1130
  :uint,
1016
1131
  :pointer,
metadata CHANGED
@@ -1,46 +1,34 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: ffi-wingui-core
3
- version: !ruby/object:Gem::Version
4
- prerelease: false
5
- segments:
6
- - 0
7
- - 1
8
- - 0
9
- version: 0.1.0
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
5
+ prerelease: !!null
10
6
  platform: ruby
11
- authors:
7
+ authors:
12
8
  - Radoslav Peev
13
- autorequire:
9
+ autorequire: !!null
14
10
  bindir: bin
15
11
  cert_chain: []
16
-
17
- date: 2011-01-26 00:00:00 +02:00
18
- default_executable:
19
- dependencies:
20
- - !ruby/object:Gem::Dependency
12
+ date: 2011-02-01 00:00:00.000000000 +02:00
13
+ default_executable: !!null
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
21
16
  name: ffi
22
- prerelease: false
23
- requirement: &id001 !ruby/object:Gem::Requirement
17
+ requirement: &22547748 !ruby/object:Gem::Requirement
24
18
  none: false
25
- requirements:
19
+ requirements:
26
20
  - - ~>
27
- - !ruby/object:Gem::Version
28
- segments:
29
- - 1
30
- - 0
31
- - 5
21
+ - !ruby/object:Gem::Version
32
22
  version: 1.0.5
33
23
  type: :runtime
34
- version_requirements: *id001
35
- description:
36
- email:
24
+ prerelease: false
25
+ version_requirements: *22547748
26
+ description: !!null
27
+ email: !!null
37
28
  executables: []
38
-
39
29
  extensions: []
40
-
41
30
  extra_rdoc_files: []
42
-
43
- files:
31
+ files:
44
32
  - lib/ffi-wingui-core.rb
45
33
  - examples/Command.rbw
46
34
  - examples/Hello.rbw
@@ -52,34 +40,26 @@ files:
52
40
  has_rdoc: true
53
41
  homepage: http://github.com/rpeev/ffi-wingui-core
54
42
  licenses: []
55
-
56
- post_install_message:
43
+ post_install_message: !!null
57
44
  rdoc_options: []
58
-
59
- require_paths:
45
+ require_paths:
60
46
  - lib
61
- required_ruby_version: !ruby/object:Gem::Requirement
47
+ required_ruby_version: !ruby/object:Gem::Requirement
62
48
  none: false
63
- requirements:
64
- - - ">="
65
- - !ruby/object:Gem::Version
66
- segments:
67
- - 0
68
- version: "0"
69
- required_rubygems_version: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - ! '>='
51
+ - !ruby/object:Gem::Version
52
+ version: '0'
53
+ required_rubygems_version: !ruby/object:Gem::Requirement
70
54
  none: false
71
- requirements:
72
- - - ">="
73
- - !ruby/object:Gem::Version
74
- segments:
75
- - 0
76
- version: "0"
55
+ requirements:
56
+ - - ! '>='
57
+ - !ruby/object:Gem::Version
58
+ version: '0'
77
59
  requirements: []
78
-
79
- rubyforge_project:
80
- rubygems_version: 1.3.7
81
- signing_key:
60
+ rubyforge_project: !!null
61
+ rubygems_version: 1.5.0
62
+ signing_key: !!null
82
63
  specification_version: 3
83
64
  summary: Ruby-FFI bindings to essential GUI-related Windows APIs
84
65
  test_files: []
85
-