2011-09-05 17 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 

güvensiz yabancı ithalat bir düğme ile basit Win32 GUI uygulamadır ama buton tıklandığında bir mesaj kutusu (22 hat) olmalıdır ancak hata vardır:Mesaj Kutusu Hata: Burada

düğmeleri .exe: program: güvensizce tekrar girildi. Belki 'yabancı bir ithalat güvensiz' güvenli olmalı mı?

Nasıl düzeltebilirim?

+3

Ben 'can t nasıl düzeltileceğini, ama bu bir hata gibi görünüyor. Muhtemelen her hangi bir paketin Graphics.Win32'yi sağladığına dair şikayette bulunmalısınız. –

cevap

5

Daniel Wagner'in söylediği gibi, bu Win32 paketindeki bir hatadır. MessageBoxW, sahip olduğu birçok yan etki nedeniyle güvenli bir şekilde alınmalıdır.

messageBox işlevi, 'unsafely' import MessageBoxW işlevi için bir sarmalayıcıdır. Güvenli olmayan bir içe aktarılmış işlev işlevi güvenli olmayan bir şekilde içe aktarıldığında Haskell, iş parçacığının geri dönene kadar herhangi bir Haskell kodunu çağırmayacağını varsayar. Ancak, MessageBoxW'u çağırırsanız, Windows 30 satırında oluşturduğunuz pencereye bir kaç pencere mesajı atar, bu nedenle güvenli olmayan bir yabancı işlevdeyken Haskell kodu çalıştırılır. Bu aynı zamanda messageBox numaralı telefonun numaralı telefonun penceresinin oluşturulmasına kadar çalışmasının nedenidir.

Olası bir geçici çözüm, yalnızca işlevi kendiniz düzeltmektir. Birincisi,

Sonra
import Graphics.Win32 hiding (messageBox, c_MessageBox) 

için

import Graphics.Win32 

değiştirmek unsafe kaldırılmış ve/veya safe eklenen, modülün Graphics.Win32.Misc den messageBox ve c_MessageBox tanımlarını kopyalamak:

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

Harika cevap Tinctorius! Bir takip soruları: – CoR

+0

1. Haskell dir'te Graphics.Win32.Misc'i nerede bulabilirim? Lib klasöründe sadece .hi dosyaları var. 2. Bu son yers böcek. Haskel paketinde neden düzeltilmediğini merak ediyor musun? – CoR

+1

1) Tanımlamayı buradan [buraya] kopyalayabilirsiniz (https://github.com/Tinctorius/win32/blob/5fc830d7e956ad890ec12d0ed29bcae6662625bd/Graphics/Win32/Misc.hsc#L127); Bu sürüm zaten düzeltilmiştir. Alternatif olarak, bir komut isteminde (şu anki dizininizde "win32" adlı bir klasör oluşturacak ve orada win32 kitaplığını indirip paketinden çıkaracaksınız) cabal 'win32' paketini açın ve sonra buna bakın. 2) Asıl bakıcı, e-postama hiçbir zaman cevap vermedi. [Github ile bir istek isteği] gönderdim (https://github.com/haskell/win32/pull/5), şimdi çok daha hızlı bir şekilde çözülmelidir :) –

İlgili konular