メッセージボックスエラー:外国のインポート安全でない
質問
import Graphics.Win32
import System.Win32.DLL
import Control.Exception (bracket)
import Foreign
import System.Exit
main :: IO ()
main = do
mainInstance <- getModuleHandle Nothing
hwnd <- createWindow_ 200 200 wndProc mainInstance
createButton_ hwnd mainInstance
messagePump hwnd
wndProc :: HWND -> WindowMessage -> WPARAM -> LPARAM -> IO LRESULT
wndProc hwnd wmsg wParam lParam
| wmsg == wM_DESTROY = do
sendMessage hwnd wM_QUIT 1 0
return 0
| wmsg == wM_COMMAND && wParam == 1 = do
messageBox nullPtr "Yahoo!!" "Message box" 0 -- Error! Why? :(
return 0
| otherwise = defWindowProc (Just hwnd) wmsg wParam lParam
createWindow_ :: Int -> Int -> WindowClosure -> HINSTANCE -> IO HWND
createWindow_ width height wndProc mainInstance = do
let winClass = mkClassName "ButtonExampleWindow"
icon <- loadIcon Nothing iDI_APPLICATION
cursor <- loadCursor Nothing iDC_ARROW
bgBrush <- createSolidBrush (rgb 240 240 240)
registerClass (cS_VREDRAW + cS_HREDRAW, mainInstance, Just icon, Just cursor, Just bgBrush, Nothing, winClass)
w <- createWindow winClass "Button example" wS_OVERLAPPEDWINDOW Nothing Nothing (Just width) (Just height) Nothing Nothing mainInstance wndProc
showWindow w sW_SHOWNORMAL
updateWindow w
return w
createButton_ :: HWND -> HINSTANCE -> IO ()
createButton_ hwnd mainInstance = do
hBtn <- createButton "Press me" wS_EX_CLIENTEDGE (bS_PUSHBUTTON + wS_VISIBLE + wS_CHILD) (Just 50) (Just 80) (Just 80) (Just 20) (Just hwnd) (Just (castUINTToPtr 1)) mainInstance
return ()
messagePump :: HWND -> IO ()
messagePump hwnd = allocaMessage $ \ msg ->
let pump = do
getMessage msg (Just hwnd) `catch` \ _ -> exitWith ExitSuccess
translateMessage msg
dispatchMessage msg
pump
in pump
ボタンを備えた単純なWin32 GUIアプリケーションは次のとおりですが、ボタンをクリックすると、メッセージボックス(22行)が必要ですが、エラーがあります。
Buttons.exe:スケジュール:危険にさらされていません。おそらく、「外国の輸入安全性」は「安全」でなければなりませんか?
どうすれば修正できますか?
解決
Daniel Wagnerがコメントしたように、これはWin32パッケージのバグです。 MessageBoxW
多くの副作用があるため、安全に輸入する必要があります。
messageBox
機能は、「安全でない」インポートのラッパーです MessageBoxW
関数。危険なインポートされた関数関数が安全でない場合、Haskellは、スレッドが戻るまでHaskellコードを呼び出さないと想定しています。ただし、電話する場合 MessageBoxW
, 、Windowsは30行目で作成したウィンドウにかなりの数のウィンドウメッセージを投げます。そのため、安全でない外国の機能中にHaskellコードが実行されます。これが呼び出しの理由でもあります messageBox
動作します それまで そのウィンドウが作成されました。
可能な回避策は、自分で機能を単純に修正することです。まず、変更
import Graphics.Win32
に
import Graphics.Win32 hiding (messageBox, c_MessageBox)
次に、の定義をコピーします messageBox
と c_MessageBox
モジュールから Graphics.Win32.Misc
, 、 と unsafe
削除および/または safe
追加した:
messageBox :: HWND -> String -> String -> MBStyle -> IO MBStatus
messageBox wnd text caption style =
withTString text $ \ c_text ->
withTString caption $ \ c_caption ->
failIfZero "MessageBox" $ c_MessageBox wnd c_text c_caption style
foreign import stdcall safe "windows.h MessageBoxW"
c_MessageBox :: HWND -> LPCTSTR -> LPCTSTR -> MBStyle -> IO MBStatus
所属していません StackOverflow