以下似乎工作......但它似乎笨拙。存在的反模式,如何避免
data Point = Point Int Int
data Box = Box Int Int
data Path = Path [Point]
data Text = Text
data Color = Color Int Int Int
data WinPaintContext = WinPaintContext Graphics.Win32.HDC
class CanvasClass vc paint where
drawLine :: vc -> paint -> Point -> Point -> IO()
drawRect :: vc -> paint -> Box -> IO()
drawPath :: vc -> paint -> Path -> IO()
class (CanvasClass vc paint) => TextBasicClass vc paint where
basicDrawText :: vc -> paint -> Point -> String -> IO()
instance CanvasClass WinPaintContext WinPaint where
drawLine = undefined
drawRect = undefined
drawPath = undefined
instance TextBasicClass WinPaintContext WinPaint where
basicDrawText (WinPaintContext a) = winBasicDrawText a
op :: CanvasClass vc paint => vc -> Box -> IO()
op canvas _ = do
basicDrawText canvas WinPaint (Point 30 30) "Hi"
open :: IO()
open = do
makeWindow (Box 300 300) op
winBasicDrawText :: Graphics.Win32.HDC -> WinPaint -> Point -> String -> IO()
winBasicDrawText hdc _ (Point x y) str = do
Graphics.Win32.setBkMode hdc Graphics.Win32.tRANSPARENT
Graphics.Win32.setTextColor hdc (Graphics.Win32.rgb 255 255 0)
Graphics.Win32.textOut hdc 20 20 str
return()
windowsOnPaint :: (WinPaintContext -> Box -> IO()) ->
Graphics.Win32.RECT ->
Graphics.Win32.HDC ->
IO()
windowsOnPaint f rect hdc = f (WinPaintContext hdc) (Box 30 30)
makeWindow :: Box -> (WinPaintContext -> Box -> IO()) -> IO()
makeWindow (Box w h) onPaint =
Graphics.Win32.allocaPAINTSTRUCT $ \ lpps -> do
hwnd <- createWindow w h (wndProc lpps (windowsOnPaint onPaint))
messagePump hwnd
現在,似乎是首選的方法是隻讓
data Canvas = Canvas {
drawLine :: Point -> Point -> IO(),
drawRect :: Box -> IO(),
drawPath :: Path -> IO()
}
hdc2Canvas :: Graphics.Win32.HDC -> Paint -> IO (Canvas)
hdc2Canvas hdc paint = Canvas { drawLine = winDrawLine hdc paint ... }
無論其...
我們喜歡讓周圍的油漆和變異他們整個拉絲工藝,因爲它們的創建和銷燬成本很高。一個paint可以是一個像[bgColor red,fgColor blue,字體「Tahoma」]之類的列表,或者它可以是一個指向內部結構的指針,這個指針是繪製系統使用的(這是對GDI的抽象,但最終會抽象通過direct2d和coregraphics),它們具有「繪畫」對象,我不想一遍又一遍地重新創建,然後綁定。
在我看來,存在的美妙之處在於,他們可以不透明地包裝某些東西來抽象它,並且我們可以將它保存在某個地方,然後將其拉回來,無論如何。當你部分申請時,我認爲存在的問題是你部分申請的東西現在「卡在」容器內。這是一個例子。說我有一個像
data Paint = Paint {
setFg :: Color -> IO() ,
setBg :: Color -> IO()
}
我在哪裏可以放置指針?當我將Paint賦予Canvas中的某個函數時,他如何獲得指針?什麼是設計這個API的正確方法?
什麼是'WinPaint'?你是否有一個主力跑着做一些事情,所以我們可以看到這是什麼意思?您希望消除的存在量化類型在哪裏? – Cirdec
WinPaint只是一種指向某種特定平臺的繪圖上下文的指針,它包含前景,背景,字體等。我沒有明確地對它們進行量化,但我會將CanvasClass量化爲Canvas。這裏的「打開」是主要的,應該只是打開一個窗口,裏面有一些文字。這段代碼不起作用,但我希望它能讓我的意圖得到解決。 – Evan
「什麼是設計此API的正確方法?」似乎更適合程序員.stackexchange.com。你會對這個問題做出不同的迴應。例如,我的開始是「擺脫IO()」或「看光澤如何去做」,這兩者都與存在量化無關。 – Cirdec