2011-09-05 14 views
5
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 जीयूआई आवेदन है लेकिन जब मैं बटन पर क्लिक करें वहाँ एक संदेश बॉक्स (22 लाइन) होना चाहिए, लेकिन वहाँ त्रुटि है:संदेश बॉक्स त्रुटि: विदेशी आयात असुरक्षित

बटन .exe: शेड्यूल: असुरक्षित रूप से पुनः दर्ज किया गया। शायद एक 'विदेशी आयात असुरक्षित' होना चाहिए 'सुरक्षित'?

मैं इसे कैसे ठीक कर सकता हूं?

+3

मैं कर सकते हैं ' टी जवाब कैसे ठीक करें, लेकिन यह एक बग की तरह दिखता है। आपको ग्राफिक्स.Win32 प्रदान करने वाले किसी भी पैकेज के रखरखाव के लिए शायद शिकायत करनी चाहिए। –

उत्तर

5

डैनियल वाग्नेर की तरह टिप्पणी की, यह Win32 पैकेज में एक बग है। MessageBoxW को इसके कई दुष्प्रभावों के कारण सुरक्षित रूप से आयात किया जाना चाहिए।

messageBox फ़ंक्शन 'असुरक्षित' आयातित MessageBoxW फ़ंक्शन के लिए एक रैपर है। जब एक असुरक्षित आयातित फ़ंक्शन फ़ंक्शन असुरक्षित रूप से आयात किया जाता है, तो हास्केल मानता है कि थ्रेड तब तक किसी भी हास्केल कोड को कॉल नहीं करेगा जब तक वह वापस न आए। हालांकि, अगर आप MessageBoxW पर कॉल करते हैं, तो विंडोज़ लाइन 30 में बनाई गई विंडो में कुछ विंडो संदेश फेंक देगा, इसलिए जब आप असुरक्षित विदेशी फ़ंक्शन में हों तो हास्केल कोड चलाया जाएगा। यही कारण है कि messageBox पर कॉल तक काम करेगा जो विंडो बनाई गई है।

एक संभावित कामकाज केवल कार्य को सही करने के लिए है। सबसे पहले,

import Graphics.Win32 hiding (messageBox, c_MessageBox) 

तब को

import Graphics.Win32 

बदल मॉड्यूल Graphics.Win32.Misc से messageBox और c_MessageBox की परिभाषा कॉपी, 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 
+0

ग्रेट उत्तर टिनक्टरियस! एक अनुवर्ती प्रश्न: – CoR

+0

1. मुझे Haskell dir में Graphics.Win32.Misc कहां मिल सकता है? मेरे पास lib फ़ोल्डर में केवल .hi फ़ाइलें हैं। 2. यह पिछले साल बग है। आश्चर्य है कि यह हास्केल पैकेज में क्यों तय नहीं किया गया है? – CoR

+1

1) आप [यहां] (https://github.com/Tinctorius/win32/blob/5fc830d7e956ad890ec12d0ed29bcae6662625bd/Graphics/Win32/Misc.hsc#L127) से परिभाषा की प्रतिलिपि बना सकते हैं; यह संस्करण पहले से ही सही है। वैकल्पिक रूप से, आप कमांड प्रॉम्प्ट पर 'कैबल अनपैक win32' कह सकते हैं (जो आपकी वर्तमान निर्देशिका में "win32" नामक फ़ोल्डर बनायेगा, और वहां Win32 लाइब्रेरी को डाउनलोड और अनपैक करेगा) और उसके बाद इसे देखें। 2) मूल रखरखाव ने कभी भी मेरे ई-मेल का जवाब नहीं दिया। मैंने [गिटूब के माध्यम से एक पुल अनुरोध] सबमिट किया है (https://github.com/haskell/win32/pull/5) अब, जिसे बहुत तेज़ हल किया जाना चाहिए :) –

संबंधित मुद्दे