GCC 下 makefile 的用法為在 command line 下執行
make -f <file> <rule>
如果不設定指定檔案, 默認執行 Makefile 這個檔案, 與 all 這個 rule.
* 在 windows MinGW 下記得將 MinGW 路徑加入環境變數, 不然會不認識 make
* 在 linux MinGW 使用 cross compiler 則用 mingw32-make -f <file> <rule>
Visual studio 下 必須先開啟 Visual studio Tools 底下的命令列模式( EX: Visual studio 2005 命令提示字元), 然後執行
NMAKE /f <file> <rule>
makefile 其他常見的 rule
make clean 清除編譯過程中所產生的文件
make distclean 清除編譯過程中所產生的文件,還有 configure
所產生的 Makefile
make install 安裝至系統
make dist 將原始碼壓縮成 *.tar.gz
make distcheck 將原始碼壓縮成 *.tar.gz 檔,並測試。
簡易 Makefile 語法解釋如下
---------------------------------------------------------------------------------------------------------------------
# 以 # 開頭的即為註解。
!include <ntwin32.mak>
# 變數宣告不分大小寫
Target=Gilgamesh.exe
# 慣例上, 給外部使用的變數名稱使用大寫
OBJECTS = Gilgamesh.obj Gilgamesh.rbj
# 利用 $(cflags) 或 ${cflags} 來存取已定義的變數
cflags = $(cflags) /openmp
# 慣例上,內部使用的變數名稱使用小寫
extdflags = -DVisualStudio -DNDEBUG -DWINDOWS
# Makefile會在展開後,再決定變數的值。
# := 表示變數的值決定於它在 Makefile 中的位置, 而不是展開後
dflags := $(extdflags) $(dflags)
# 取消該變數
LIB_DIR=
# ?= 若變數未定義,則替它指定新的值。否則,採用原有的值。
FOO ?= wtf
# 與C語法相同, 自身再加上數值
cflags += -O2
# rule 功用為指示如何進行編譯
all: $(Target)
# <target>:<dependencies>
# target:要建立的檔案
# dependencies:相依項目。決定是否要重新編譯。
Gilgamesh.obj: Gilgamesh.c
# 建立檔案的指令, 前面必須是 Tab, 不能為空白, 所有 Tab 開頭會被視為 shell script / batch 指令
$(cc) $(cflags) $(cvars) $(dflags) $(hflags) Gilgamesh.c
Gilgamesh.res: Gilgamesh.rc
$(rc) -DWIN32 -DNDEBUG $(hflags) -r Gilgamesh.rc
Gilgamesh.rbj: Gilgamesh.res
cvtres $(cvflags) -machine:ix86 -o Gilgamesh.rbj Gilgamesh.res
$(Target): $(OBJECTS)
$(link) /libpath:$(LIB_DIR) /out:$(Target) $(OBJECTS)
clean:
# @:不要顯示執行的指令。
# \:換行用
@for %%x in (obj exp pdb ilk res rbj) do \
if exist *.%%x del *.%%x
# -:指令出錯也不中斷執行。
-for %%x in (exe dll lib) do if exist Gilgamesh.%%x del Gilgamesh.%%x
---------------------------------------------------------------------------------------------------------------------
因為我很懶, 通常我會將命令先寫成 *.bat 或 *.sh
Windows MinGW32 範例 gcc.bat
---------------------------------------------------------------------------------------------------------------------
@ECHO off
SET GCCBIN=c:\MinGW\bin
SET GCCMAKE=C:\MinGW\msys\1.0\bin
SET path=%GCCBIN%;%GCCMAKE%;%path%
IF EXIST %GCCBIN%\gcc.exe (
GOTO HELL
)
ECHO can not find MinGW
PAUSE
GOTO :EOF
:HELL
make -f WindowsGCC.mak clean
make -f WindowsGCC.mak ALL
---------------------------------------------------------------------------------------------------------------------
Windows visual studio 範例 vc2005.bat
---------------------------------------------------------------------------------------------------------------------
@echo off
IF EXIST "%VS80COMNTOOLS%vsvars32.bat" (
call "%VS80COMNTOOLS%vsvars32.bat"
GOTO HELL
)
ECHO can not find visual studio
PAUSE
GOTO :EOF
:HELL
NMAKE /f "WindowsVC.mak" clean
NMAKE /f "WindowsVC.mak" ALL
---------------------------------------------------------------------------------------------------------------------
Linux gcc 範例 gcc.sh
---------------------------------------------------------------------------------------------------------------------
make -f ./Makefile clean
make -f ./Makefile all
---------------------------------------------------------------------------------------------------------------------
2014年12月9日 星期二
openSSL 1.0.1e 編譯
0. 現成編好的
http://slproweb.com/products/Win32OpenSSL.html
1. 必要條件
openssl source code (使用版本為 openssl-1.0.1e)
activeperl
NASM (非必要, 有會比較快, 快在哪? ...阿栽.)
Microsoft Visual Studio (這邊用的為 vs2005)
2. 編譯環境
安裝 activeperl, NASM, 將 NASM 安裝路徑加入系統path裡
開啟 程式集->Microsoft Visual Studio 2005->Visual Studio Tools->Visual Studio 2005 Command Prompt
(編譯X64 就開啟 Visual Studio 2005 x64 Win64 Command Prompt, IA64依此類推)
* 2005 64bit compiler 預設是沒安裝的, 要用記得安裝一下
3. 移動到目錄
>cd D:\openssl-1.0.1e
4. 指定編譯類型
X86
>perl Configure VC-WIN32 no-asm
or
>perl Configure VC-WIN32
X64
>perl Configure VC-WIN64A no-asm
IA64
>perl Configure VC-WIN64I no-asm
5. 製造編譯用 *.mak 檔
X86
>ms\do_ms.bat
or
>ms\do_nasm.bat
X64
>ms\do_win64a.bat
IA64
>ms\do_win64i.bat
6. 編譯
先修改 ms\ntdll.mak , 將 CFLAG= /MD ... 改為 CFLAG= /MT ...
nmake -f ms\ntdll.mak 動態連結
or
nmake -f ms\nt.mak 靜態連結
7. 產出
D:\openssl-1.0.1e\outdll32
or
D:\openssl-1.0.1e\out32
ssleay32.lib 實現SSL協議
libeay32.lib 實現各種演算法
8. 懶人用 batch
REM VS2005 X86
@echo off
IF NOT EXIST "%VS80COMNTOOLS%vsvars32.bat" (
ECHO can not find visual studio 2005
PAUSE
GOTO :EOF
)
call "%VS80COMNTOOLS%vsvars32.bat"
SET OPENSSLDIR=.\openssl-1.0.1e
SET OUTPUTDIR=.\OpenSSL_VC2005_X86
CD %OPENSSLDIR%
perl Configure VC-WIN32
start /wait cmd.exe /c .\ms\do_nasm.bat
nmake -f .\ms\nt.mak
nmake -f .\ms\nt.mak clean
CD ..
IF EXIST %OUTPUTDIR% (
DEL %OUTPUTDIR%\libeay32.lib
DEL %OUTPUTDIR%\ssleay32.lib
DEL %OUTPUTDIR%\openssl.exe
) else (
MKDIR %OUTPUTDIR%
)
COPY %OPENSSLDIR%\out32\libeay32.lib %OUTPUTDIR%\libeay32.lib
COPY %OPENSSLDIR%\out32\ssleay32.lib %OUTPUTDIR%\ssleay32.lib
COPY %OPENSSLDIR%\out32\openssl.exe %OUTPUTDIR%\openssl.exe
DEL %OPENSSLDIR%\out32\libeay32.lib
DEL %OPENSSLDIR%\out32\ssleay32.lib
DEL %OPENSSLDIR%\out32\openssl.exe
-------------------------------------------------------------------------------------------------------------
REM VS2005 X64
@echo off
SET CompilerBat="C:\Program Files\Microsoft Visual Studio 8\VC\bin\amd64\vcvarsamd64.bat"
IF EXIST %CompilerBat% (
CALL %CompilerBat%
GOTO BuildProject
}
SET CompilerBat="C:\Program Files (x86)\Microsoft Visual Studio 8\VC\bin\amd64\vcvarsamd64.bat"
IF EXIST %CompilerBat% (
CALL %CompilerBat%
GOTO BuildProject
)
ECHO can not find visual studio 2005
PAUSE
GOTO :EOF
:BuildProject
SET OPENSSLDIR=.\openssl-1.0.1e
SET OUTPUTDIR=.\OpenSSL_VC2005_X64
CD %OPENSSLDIR%
perl Configure VC-WIN64A no-asm
start /wait cmd.exe /c .\ms\do_win64a.bat
nmake -f .\ms\nt.mak
nmake -f .\ms\nt.mak clean
CD ..
IF EXIST %OUTPUTDIR% (
DEL %OUTPUTDIR%\libeay32.lib
DEL %OUTPUTDIR%\ssleay32.lib
DEL %OUTPUTDIR%\openssl.exe
) else (
MKDIR %OUTPUTDIR%
)
COPY %OPENSSLDIR%\out32\libeay32.lib %OUTPUTDIR%\libeay32.lib
COPY %OPENSSLDIR%\out32\ssleay32.lib %OUTPUTDIR%\ssleay32.lib
COPY %OPENSSLDIR%\out32\openssl.exe %OUTPUTDIR%\openssl.exe
DEL %OPENSSLDIR%\out32\libeay32.lib
DEL %OPENSSLDIR%\out32\ssleay32.lib
DEL %OPENSSLDIR%\out32\openssl.exe
-------------------------------------------------------------------------------------------------------------
http://slproweb.com/products/Win32OpenSSL.html
1. 必要條件
openssl source code (使用版本為 openssl-1.0.1e)
activeperl
NASM (非必要, 有會比較快, 快在哪? ...阿栽.)
Microsoft Visual Studio (這邊用的為 vs2005)
2. 編譯環境
安裝 activeperl, NASM, 將 NASM 安裝路徑加入系統path裡
開啟 程式集->Microsoft Visual Studio 2005->Visual Studio Tools->Visual Studio 2005 Command Prompt
(編譯X64 就開啟 Visual Studio 2005 x64 Win64 Command Prompt, IA64依此類推)
* 2005 64bit compiler 預設是沒安裝的, 要用記得安裝一下
3. 移動到目錄
>cd D:\openssl-1.0.1e
4. 指定編譯類型
X86
>perl Configure VC-WIN32 no-asm
or
>perl Configure VC-WIN32
X64
>perl Configure VC-WIN64A no-asm
IA64
>perl Configure VC-WIN64I no-asm
5. 製造編譯用 *.mak 檔
X86
>ms\do_ms.bat
or
>ms\do_nasm.bat
X64
>ms\do_win64a.bat
IA64
>ms\do_win64i.bat
6. 編譯
先修改 ms\ntdll.mak , 將 CFLAG= /MD ... 改為 CFLAG= /MT ...
nmake -f ms\ntdll.mak 動態連結
or
nmake -f ms\nt.mak 靜態連結
7. 產出
D:\openssl-1.0.1e\outdll32
or
D:\openssl-1.0.1e\out32
ssleay32.lib 實現SSL協議
libeay32.lib 實現各種演算法
8. 懶人用 batch
REM VS2005 X86
@echo off
IF NOT EXIST "%VS80COMNTOOLS%vsvars32.bat" (
ECHO can not find visual studio 2005
PAUSE
GOTO :EOF
)
call "%VS80COMNTOOLS%vsvars32.bat"
SET OPENSSLDIR=.\openssl-1.0.1e
SET OUTPUTDIR=.\OpenSSL_VC2005_X86
CD %OPENSSLDIR%
perl Configure VC-WIN32
start /wait cmd.exe /c .\ms\do_nasm.bat
nmake -f .\ms\nt.mak
nmake -f .\ms\nt.mak clean
CD ..
IF EXIST %OUTPUTDIR% (
DEL %OUTPUTDIR%\libeay32.lib
DEL %OUTPUTDIR%\ssleay32.lib
DEL %OUTPUTDIR%\openssl.exe
) else (
MKDIR %OUTPUTDIR%
)
COPY %OPENSSLDIR%\out32\libeay32.lib %OUTPUTDIR%\libeay32.lib
COPY %OPENSSLDIR%\out32\ssleay32.lib %OUTPUTDIR%\ssleay32.lib
COPY %OPENSSLDIR%\out32\openssl.exe %OUTPUTDIR%\openssl.exe
DEL %OPENSSLDIR%\out32\libeay32.lib
DEL %OPENSSLDIR%\out32\ssleay32.lib
DEL %OPENSSLDIR%\out32\openssl.exe
-------------------------------------------------------------------------------------------------------------
REM VS2005 X64
@echo off
SET CompilerBat="C:\Program Files\Microsoft Visual Studio 8\VC\bin\amd64\vcvarsamd64.bat"
IF EXIST %CompilerBat% (
CALL %CompilerBat%
GOTO BuildProject
}
SET CompilerBat="C:\Program Files (x86)\Microsoft Visual Studio 8\VC\bin\amd64\vcvarsamd64.bat"
IF EXIST %CompilerBat% (
CALL %CompilerBat%
GOTO BuildProject
)
ECHO can not find visual studio 2005
PAUSE
GOTO :EOF
:BuildProject
SET OPENSSLDIR=.\openssl-1.0.1e
SET OUTPUTDIR=.\OpenSSL_VC2005_X64
CD %OPENSSLDIR%
perl Configure VC-WIN64A no-asm
start /wait cmd.exe /c .\ms\do_win64a.bat
nmake -f .\ms\nt.mak
nmake -f .\ms\nt.mak clean
CD ..
IF EXIST %OUTPUTDIR% (
DEL %OUTPUTDIR%\libeay32.lib
DEL %OUTPUTDIR%\ssleay32.lib
DEL %OUTPUTDIR%\openssl.exe
) else (
MKDIR %OUTPUTDIR%
)
COPY %OPENSSLDIR%\out32\libeay32.lib %OUTPUTDIR%\libeay32.lib
COPY %OPENSSLDIR%\out32\ssleay32.lib %OUTPUTDIR%\ssleay32.lib
COPY %OPENSSLDIR%\out32\openssl.exe %OUTPUTDIR%\openssl.exe
DEL %OPENSSLDIR%\out32\libeay32.lib
DEL %OPENSSLDIR%\out32\ssleay32.lib
DEL %OPENSSLDIR%\out32\openssl.exe
-------------------------------------------------------------------------------------------------------------
2014年12月8日 星期一
python 上一個簡單的 trace tools
寫程式時很怕測試人員沒頭沒尾的回報, 還是丟了一個用克林貢語寫的 bug 描述.
所以我都會額外自己發展一個小工具讓程序輸出 log, 讓測試人員回報用.
ptlog.py
#-------------------------------------------------------------------------------
# Name: ptlog
# Purpose:
#
# Author: nanoha
#
# Created: 10/12/2013
# Copyright: (c) nanoha 2013
# Licence: no licence
#-------------------------------------------------------------------------------
import os, inspect, sys
from time import strftime
__author__ = "nanoha <nanoha@nanoha.org>"
__status__ = "production"
__version__ = "0.0.6.0"
__date__ = "2014-05-07"
__IsPrint = True
if (os.name == 'nt'):
__output = u'C:\\temp\\pt.txt'
elif (os.name == 'posix'):
__output = u'/temp/pt.txt'
def SetOutput(szLog):
global __output
__output = szLog
def IsPrint(bPrint):
global __IsPrint
__IsPrint = bPrint
def __WriteFile(szFileName, szFuncName, szMsgline, szFlag, szMsg):
hFile = None
try:
now = strftime('%Y-%m-%d %H:%M:%S')
szFormatMsg = '[%s][%s][%s][%s][%s]%s\n' % ( now, szFileName, szFuncName, szMsgline, szFlag, szMsg)
hFile = open(__output, 'a+')
hFile.write(szFormatMsg)
except Exception as error:
try:
now = strftime('%Y-%m-%d %H:%M:%S')
szFormatMsg = u'[%s][%s][%s][%s][%s]%s\n' % (unicode(now), unicode(szFileName), unicode(szFuncName), unicode(szMsgline), unicode(szFlag), unicode(error))
hFile = open(__output, 'a+')
hFile.write(szFormatMsg.encode('utf-8'))
except Exception as error:
print error
finally:
if hFile:
hFile.close()
def PTError(szMsg):
try:
Callerframel = inspect.stack()[1][0]
if (__IsPrint):
print '[%s][%s][%s][%s]%s' % (Callerframel.f_code.co_filename, Callerframel.f_code.co_name, Callerframel.f_lineno, 'PTERROR', szMsg)
if (os.path.exists(__output)):
__WriteFile(Callerframel.f_code.co_filename, Callerframel.f_code.co_name, Callerframel.f_lineno, 'PTERROR', szMsg)
except Exception as error:
pass
def convertToStr(szMsg):
ret = ''
try:
if isinstance(szMsg, unicode):
ret = szMsg.encode('utf-8')
elif isinstance(szMsg, str):
ret = szMsg
except Exception as error:
PTError(str(error))
finally:
return ret
def debug(szMsg):
Callerframel = inspect.stack()[1][0]
if (__IsPrint):
try:
print '[%s][%s][%s][%s]%s' % (Callerframel.f_code.co_filename, Callerframel.f_code.co_name, Callerframel.f_lineno, 'DEBUG', szMsg)
except Exception as error:
PTError(str(error))
if (os.path.exists(__output)):
szMsg = convertToStr(szMsg)
if szMsg:
__WriteFile(Callerframel.f_code.co_filename, Callerframel.f_code.co_name, Callerframel.f_lineno, 'DEBUG', szMsg)
def info(szMsg):
Callerframel = inspect.stack()[1][0]
if (__IsPrint):
try:
print '[%s][%s][%s][%s]%s' % (Callerframel.f_code.co_filename, Callerframel.f_code.co_name, Callerframel.f_lineno, 'INFO', szMsg)
except Exception as error:
PTError(str(error))
if (os.path.exists(__output)):
szMsg = convertToStr(szMsg)
if szMsg:
__WriteFile(Callerframel.f_code.co_filename, Callerframel.f_code.co_name, Callerframel.f_lineno, 'INFO', szMsg)
def warning(szMsg):
Callerframel = inspect.stack()[1][0]
if (__IsPrint):
try:
print '[%s][%s][%s][%s]%s' % (Callerframel.f_code.co_filename, Callerframel.f_code.co_name, Callerframel.f_lineno, 'WARNING', szMsg)
except Exception as error:
PTError(str(error))
if (os.path.exists(__output)):
szMsg = convertToStr(szMsg)
if szMsg:
__WriteFile(Callerframel.f_code.co_filename, Callerframel.f_code.co_name, Callerframel.f_lineno, 'WARNING', szMsg)
def error(szMsg):
Callerframel = inspect.stack()[1][0]
if (__IsPrint):
try:
print '[%s][%s][%s][%s]%s' % (Callerframel.f_code.co_filename, Callerframel.f_code.co_name, Callerframel.f_lineno, 'ERROR', szMsg)
except Exception as error:
PTError(str(error))
if (os.path.exists(__output)):
szMsg = convertToStr(szMsg)
if szMsg:
__WriteFile(Callerframel.f_code.co_filename, Callerframel.f_code.co_name, Callerframel.f_lineno, 'ERROR', szMsg)
def critical(szMsg):
Callerframel = inspect.stack()[1][0]
if (__IsPrint):
try:
print '[%s][%s][%s][%s]%s' % (Callerframel.f_code.co_filename, Callerframel.f_code.co_name, Callerframel.f_lineno, 'CRITICAL', szMsg)
except Exception as error:
PTError(str(error))
if (os.path.exists(__output)):
szMsg = convertToStr(szMsg)
if szMsg:
__WriteFile(Callerframel.f_code.co_filename, Callerframel.f_code.co_name, Callerframel.f_lineno, 'CRITICAL', szMsg)
#-------------------------------------------------------------------------------
測試, 如果 C:\\temp\\pt.txt 不存在則不輸出,
要輸出別的名稱可用 ptlog.SetOutput('.\\a.txt')
#-------------------------------------------------------------------------------
import ptlog
def main():
ptlog.debug('test 1')
ptlog.info('test 2')
ptlog.warning('test 3')
ptlog.error('test 4')
ptlog.critical('test 5')
if __name__ == '__main__':
main()
#-------------------------------------------------------------------------------
所以我都會額外自己發展一個小工具讓程序輸出 log, 讓測試人員回報用.
ptlog.py
#-------------------------------------------------------------------------------
# Name: ptlog
# Purpose:
#
# Author: nanoha
#
# Created: 10/12/2013
# Copyright: (c) nanoha 2013
# Licence: no licence
#-------------------------------------------------------------------------------
import os, inspect, sys
from time import strftime
__author__ = "nanoha <nanoha@nanoha.org>"
__status__ = "production"
__version__ = "0.0.6.0"
__date__ = "2014-05-07"
__IsPrint = True
if (os.name == 'nt'):
__output = u'C:\\temp\\pt.txt'
elif (os.name == 'posix'):
__output = u'/temp/pt.txt'
def SetOutput(szLog):
global __output
__output = szLog
def IsPrint(bPrint):
global __IsPrint
__IsPrint = bPrint
def __WriteFile(szFileName, szFuncName, szMsgline, szFlag, szMsg):
hFile = None
try:
now = strftime('%Y-%m-%d %H:%M:%S')
szFormatMsg = '[%s][%s][%s][%s][%s]%s\n' % ( now, szFileName, szFuncName, szMsgline, szFlag, szMsg)
hFile = open(__output, 'a+')
hFile.write(szFormatMsg)
except Exception as error:
try:
now = strftime('%Y-%m-%d %H:%M:%S')
szFormatMsg = u'[%s][%s][%s][%s][%s]%s\n' % (unicode(now), unicode(szFileName), unicode(szFuncName), unicode(szMsgline), unicode(szFlag), unicode(error))
hFile = open(__output, 'a+')
hFile.write(szFormatMsg.encode('utf-8'))
except Exception as error:
print error
finally:
if hFile:
hFile.close()
def PTError(szMsg):
try:
Callerframel = inspect.stack()[1][0]
if (__IsPrint):
print '[%s][%s][%s][%s]%s' % (Callerframel.f_code.co_filename, Callerframel.f_code.co_name, Callerframel.f_lineno, 'PTERROR', szMsg)
if (os.path.exists(__output)):
__WriteFile(Callerframel.f_code.co_filename, Callerframel.f_code.co_name, Callerframel.f_lineno, 'PTERROR', szMsg)
except Exception as error:
pass
def convertToStr(szMsg):
ret = ''
try:
if isinstance(szMsg, unicode):
ret = szMsg.encode('utf-8')
elif isinstance(szMsg, str):
ret = szMsg
except Exception as error:
PTError(str(error))
finally:
return ret
def debug(szMsg):
Callerframel = inspect.stack()[1][0]
if (__IsPrint):
try:
print '[%s][%s][%s][%s]%s' % (Callerframel.f_code.co_filename, Callerframel.f_code.co_name, Callerframel.f_lineno, 'DEBUG', szMsg)
except Exception as error:
PTError(str(error))
if (os.path.exists(__output)):
szMsg = convertToStr(szMsg)
if szMsg:
__WriteFile(Callerframel.f_code.co_filename, Callerframel.f_code.co_name, Callerframel.f_lineno, 'DEBUG', szMsg)
def info(szMsg):
Callerframel = inspect.stack()[1][0]
if (__IsPrint):
try:
print '[%s][%s][%s][%s]%s' % (Callerframel.f_code.co_filename, Callerframel.f_code.co_name, Callerframel.f_lineno, 'INFO', szMsg)
except Exception as error:
PTError(str(error))
if (os.path.exists(__output)):
szMsg = convertToStr(szMsg)
if szMsg:
__WriteFile(Callerframel.f_code.co_filename, Callerframel.f_code.co_name, Callerframel.f_lineno, 'INFO', szMsg)
def warning(szMsg):
Callerframel = inspect.stack()[1][0]
if (__IsPrint):
try:
print '[%s][%s][%s][%s]%s' % (Callerframel.f_code.co_filename, Callerframel.f_code.co_name, Callerframel.f_lineno, 'WARNING', szMsg)
except Exception as error:
PTError(str(error))
if (os.path.exists(__output)):
szMsg = convertToStr(szMsg)
if szMsg:
__WriteFile(Callerframel.f_code.co_filename, Callerframel.f_code.co_name, Callerframel.f_lineno, 'WARNING', szMsg)
def error(szMsg):
Callerframel = inspect.stack()[1][0]
if (__IsPrint):
try:
print '[%s][%s][%s][%s]%s' % (Callerframel.f_code.co_filename, Callerframel.f_code.co_name, Callerframel.f_lineno, 'ERROR', szMsg)
except Exception as error:
PTError(str(error))
if (os.path.exists(__output)):
szMsg = convertToStr(szMsg)
if szMsg:
__WriteFile(Callerframel.f_code.co_filename, Callerframel.f_code.co_name, Callerframel.f_lineno, 'ERROR', szMsg)
def critical(szMsg):
Callerframel = inspect.stack()[1][0]
if (__IsPrint):
try:
print '[%s][%s][%s][%s]%s' % (Callerframel.f_code.co_filename, Callerframel.f_code.co_name, Callerframel.f_lineno, 'CRITICAL', szMsg)
except Exception as error:
PTError(str(error))
if (os.path.exists(__output)):
szMsg = convertToStr(szMsg)
if szMsg:
__WriteFile(Callerframel.f_code.co_filename, Callerframel.f_code.co_name, Callerframel.f_lineno, 'CRITICAL', szMsg)
#-------------------------------------------------------------------------------
測試, 如果 C:\\temp\\pt.txt 不存在則不輸出,
要輸出別的名稱可用 ptlog.SetOutput('.\\a.txt')
#-------------------------------------------------------------------------------
import ptlog
def main():
ptlog.debug('test 1')
ptlog.info('test 2')
ptlog.warning('test 3')
ptlog.error('test 4')
ptlog.critical('test 5')
if __name__ == '__main__':
main()
#-------------------------------------------------------------------------------
獲取 windows 上安裝的所有 browser
上頭丟了一個奇怪的需求, 說我們軟件開啟的網頁要能指定 browser.
當下只有 囧 可以形容.
要知道什麼軟件是瀏覽器, 目前大概只能針對已知的 browser 個別處理.
首先要做的是就是先獲取 browser 執行檔的路徑.
所有 browser 安裝後一定會產生 Shortcut, 從 Shortcut 取得就ok了
1. 所以先取得所有 *.lnk 在 start menu下的.
wchar_t szPath[MAX_PATH];
CFileInfoList files;
memset(szPath, 0x00, sizeof(szPath));
if (SHGetSpecialFolderPathW(NULL, szPath, CSIDL_PROGRAMS, false))
{
files.GetFolderInfo(szPath);
}
memset(szPath, 0x00, sizeof(szPath));
if (SHGetSpecialFolderPathW(NULL, szPath, CSIDL_COMMON_PROGRAMS, false))
{
files.GetFolderInfo(szPath);
}
2. 接著寫取得快捷路徑的方法:
BOOL GetShortcutTarget(const wchar_t *file, CString &szTarget)
{
HRESULT hr;
IShellLinkW *pLink; //IShellLink对象指针
IPersistFile *ppf; //IPersisFil对象指针
wchar_t szPah[MAX_PATH];
WIN32_FIND_DATAW FileData;
szTarget.Empty();
hr = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLinkW, (void**)&pLink);
if (FAILED(hr))
{
SAVELOG_DANGER("CoCreateInstance failed");
return FALSE;
}
//从IShellLink对象中获取IPersistFile接口
hr = pLink->QueryInterface(IID_IPersistFile, (void**)&ppf);
if (FAILED(hr))
{
SAVELOG_DANGER("QueryInterface failed");
pLink->Release();
return FALSE;
}
// open Shortcut
hr = ppf->Load(file, STGM_READ);
if (SUCCEEDED(hr))
{
memset(szPah, 0x00, sizeof(szPah));
hr = pLink->GetPath(szPah, MAX_PATH, &FileData, SLGP_SHORTPATH);
if (SUCCEEDED(hr))
{
szTarget = szPah;
}
}
ppf->Release();
pLink->Release();
return SUCCEEDED(hr);
}
3. 針對特定名稱快捷取路徑
Internet Explorer.lnk
Mozilla Firefox.lnk
Waterfox.lnk
Navigator.lnk
Pale Moon.lnk
SeaMonkey.lnk
Google Chrome.lnk
Safari.lnk
Opera.lnk
4. 針對 Safari 處理
Safari 的快捷長的不大一樣, 所以取不到路徑, 改成取 Working Directory 並加檔案名稱
BOOL GetShortcutWorkDirectory(const wchar_t *file, CString &szDir)
{
HRESULT hr;
IShellLinkW *pLink; //IShellLink对象指针
IPersistFile *ppf; //IPersisFil对象指针
wchar_t szPah[MAX_PATH];
WIN32_FIND_DATAW FileData;
szDir.Empty();
hr = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLinkW, (void**)&pLink);
if (FAILED(hr))
{
SAVELOG_DANGER("CoCreateInstance failed");
return FALSE;
}
//从IShellLink对象中获取IPersistFile接口
hr = pLink->QueryInterface(IID_IPersistFile, (void**)&ppf);
if (FAILED(hr))
{
SAVELOG_DANGER("QueryInterface failed");
pLink->Release();
return FALSE;
}
// open Shortcut
hr = ppf->Load(file, STGM_READ);
if (SUCCEEDED(hr))
{
memset(szPah, 0x00, sizeof(szPah));
hr = pLink->GetWorkingDirectory(szPah, MAX_PATH);
if (SUCCEEDED(hr))
{
szDir = szPah;
}
}
ppf->Release();
pLink->Release();
return SUCCEEDED(hr);
}
5. 最後成果
// define by windows
unit = new CBrowserList::CBrowserInfo();
unit->m_Name = PTwcsdup(g_Language.GetString("default", "Default"));
unit->m_Path = PTwcsdup(L"");
this->m_list.Add(unit);
memset(szPath, 0x00, sizeof(szPath));
if (SHGetSpecialFolderPathW(NULL, szPath, CSIDL_PROGRAMS, false))
{
files.GetFolderInfo(szPath);
for (i=0; i<files.Count(); i++)
{
_GetFileName(files[i]->fullName, FileName);
if (0 == FileName.CompareNoCase(L"Internet Explorer.lnk"))
{
if (GetShortcutTarget(files[i]->fullName, Target))
{
unit = new CBrowserList::CBrowserInfo();
unit->m_Name = PTwcsdup(L"Internet Explorer");
unit->m_Path = PTwcsdup(Target);
this->m_list.Add(unit);
}
}
}
}
memset(szPath, 0x00, sizeof(szPath));
if (SHGetSpecialFolderPathW(NULL, szPath, CSIDL_COMMON_PROGRAMS, false))
{
files.GetFolderInfo(szPath);
for (i=0; i<files.Count(); i++)
{
_GetFileName(files[i]->fullName, FileName);
if (0 == FileName.CompareNoCase(L"Mozilla Firefox.lnk"))
{
if (GetShortcutTarget(files[i]->fullName, Target))
{
unit = new CBrowserList::CBrowserInfo();
unit->m_Name = PTwcsdup(L"Mozilla Firefox");
unit->m_Path = PTwcsdup(Target);
this->m_list.Add(unit);
}
}
else if (0 == FileName.CompareNoCase(L"Waterfox.lnk"))
{
if (GetShortcutTarget(files[i]->fullName, Target))
{
unit = new CBrowserList::CBrowserInfo();
unit->m_Name = PTwcsdup(L"Waterfox");
unit->m_Path = PTwcsdup(Target);
this->m_list.Add(unit);
}
}
else if (0 == FileName.CompareNoCase(L"Navigator.lnk"))
{
if (GetShortcutTarget(files[i]->fullName, Target))
{
unit = new CBrowserList::CBrowserInfo();
unit->m_Name = PTwcsdup(L"Navigator");
unit->m_Path = PTwcsdup(Target);
this->m_list.Add(unit);
}
}
else if (0 == FileName.CompareNoCase(L"Pale Moon.lnk"))
{
if (GetShortcutTarget(files[i]->fullName, Target))
{
unit = new CBrowserList::CBrowserInfo();
unit->m_Name = PTwcsdup(L"Pale Moon");
unit->m_Path = PTwcsdup(Target);
this->m_list.Add(unit);
}
}
else if (0 == FileName.CompareNoCase(L"SeaMonkey.lnk"))
{
if (GetShortcutTarget(files[i]->fullName, Target))
{
unit = new CBrowserList::CBrowserInfo();
unit->m_Name = PTwcsdup(L"SeaMonkey");
unit->m_Path = PTwcsdup(Target);
this->m_list.Add(unit);
}
}
else if (0 == FileName.CompareNoCase(L"Google Chrome.lnk"))
{
if (GetShortcutTarget(files[i]->fullName, Target))
{
unit = new CBrowserList::CBrowserInfo();
unit->m_Name = PTwcsdup(L"Google Chrome");
unit->m_Path = PTwcsdup(Target);
this->m_list.Add(unit);
}
}
else if (0 == FileName.CompareNoCase(L"Safari.lnk"))
{
if (GetShortcutWorkDirectory(files[i]->fullName, Target))
{
unit = new CBrowserList::CBrowserInfo();
unit->m_Name = PTwcsdup(L"Safari");
unit->m_Path = PTwcsdup(Target);
unit->m_Path = PTwcscat(unit->m_Path, L"Safari.exe");
this->m_list.Add(unit);
}
}
else if (0 == FileName.CompareNoCase(L"Opera.lnk"))
{
if (GetShortcutTarget(files[i]->fullName, Target))
{
unit = new CBrowserList::CBrowserInfo();
unit->m_Name = PTwcsdup(L"Opera");
unit->m_Path = PTwcsdup(Target);
this->m_list.Add(unit);
}
}
}
}
6. 呼叫
void openURL(const wchar_t *url)
{
if (g_SettingsInfo.Browser.IsEmpty())
{
ShellExecuteW(NULL, L"open", url, NULL, NULL, SW_SHOWNORMAL);
return;
}
// check Browser was exist
if (FileExists(g_SettingsInfo.Browser.GetString()))
{
ShellExecuteW(NULL, NULL, g_SettingsInfo.Browser.GetString(), url, NULL, SW_SHOWNORMAL);
return;
}
//
ShellExecuteW(NULL, _T("open"), url, NULL, NULL, SW_SHOWNORMAL);
}
當下只有 囧 可以形容.
要知道什麼軟件是瀏覽器, 目前大概只能針對已知的 browser 個別處理.
首先要做的是就是先獲取 browser 執行檔的路徑.
所有 browser 安裝後一定會產生 Shortcut, 從 Shortcut 取得就ok了
1. 所以先取得所有 *.lnk 在 start menu下的.
wchar_t szPath[MAX_PATH];
CFileInfoList files;
memset(szPath, 0x00, sizeof(szPath));
if (SHGetSpecialFolderPathW(NULL, szPath, CSIDL_PROGRAMS, false))
{
files.GetFolderInfo(szPath);
}
memset(szPath, 0x00, sizeof(szPath));
if (SHGetSpecialFolderPathW(NULL, szPath, CSIDL_COMMON_PROGRAMS, false))
{
files.GetFolderInfo(szPath);
}
2. 接著寫取得快捷路徑的方法:
BOOL GetShortcutTarget(const wchar_t *file, CString &szTarget)
{
HRESULT hr;
IShellLinkW *pLink; //IShellLink对象指针
IPersistFile *ppf; //IPersisFil对象指针
wchar_t szPah[MAX_PATH];
WIN32_FIND_DATAW FileData;
szTarget.Empty();
hr = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLinkW, (void**)&pLink);
if (FAILED(hr))
{
SAVELOG_DANGER("CoCreateInstance failed");
return FALSE;
}
//从IShellLink对象中获取IPersistFile接口
hr = pLink->QueryInterface(IID_IPersistFile, (void**)&ppf);
if (FAILED(hr))
{
SAVELOG_DANGER("QueryInterface failed");
pLink->Release();
return FALSE;
}
// open Shortcut
hr = ppf->Load(file, STGM_READ);
if (SUCCEEDED(hr))
{
memset(szPah, 0x00, sizeof(szPah));
hr = pLink->GetPath(szPah, MAX_PATH, &FileData, SLGP_SHORTPATH);
if (SUCCEEDED(hr))
{
szTarget = szPah;
}
}
ppf->Release();
pLink->Release();
return SUCCEEDED(hr);
}
3. 針對特定名稱快捷取路徑
Internet Explorer.lnk
Mozilla Firefox.lnk
Waterfox.lnk
Navigator.lnk
Pale Moon.lnk
SeaMonkey.lnk
Google Chrome.lnk
Safari.lnk
Opera.lnk
4. 針對 Safari 處理
Safari 的快捷長的不大一樣, 所以取不到路徑, 改成取 Working Directory 並加檔案名稱
BOOL GetShortcutWorkDirectory(const wchar_t *file, CString &szDir)
{
HRESULT hr;
IShellLinkW *pLink; //IShellLink对象指针
IPersistFile *ppf; //IPersisFil对象指针
wchar_t szPah[MAX_PATH];
WIN32_FIND_DATAW FileData;
szDir.Empty();
hr = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLinkW, (void**)&pLink);
if (FAILED(hr))
{
SAVELOG_DANGER("CoCreateInstance failed");
return FALSE;
}
//从IShellLink对象中获取IPersistFile接口
hr = pLink->QueryInterface(IID_IPersistFile, (void**)&ppf);
if (FAILED(hr))
{
SAVELOG_DANGER("QueryInterface failed");
pLink->Release();
return FALSE;
}
// open Shortcut
hr = ppf->Load(file, STGM_READ);
if (SUCCEEDED(hr))
{
memset(szPah, 0x00, sizeof(szPah));
hr = pLink->GetWorkingDirectory(szPah, MAX_PATH);
if (SUCCEEDED(hr))
{
szDir = szPah;
}
}
ppf->Release();
pLink->Release();
return SUCCEEDED(hr);
}
5. 最後成果
// define by windows
unit = new CBrowserList::CBrowserInfo();
unit->m_Name = PTwcsdup(g_Language.GetString("default", "Default"));
unit->m_Path = PTwcsdup(L"");
this->m_list.Add(unit);
memset(szPath, 0x00, sizeof(szPath));
if (SHGetSpecialFolderPathW(NULL, szPath, CSIDL_PROGRAMS, false))
{
files.GetFolderInfo(szPath);
for (i=0; i<files.Count(); i++)
{
_GetFileName(files[i]->fullName, FileName);
if (0 == FileName.CompareNoCase(L"Internet Explorer.lnk"))
{
if (GetShortcutTarget(files[i]->fullName, Target))
{
unit = new CBrowserList::CBrowserInfo();
unit->m_Name = PTwcsdup(L"Internet Explorer");
unit->m_Path = PTwcsdup(Target);
this->m_list.Add(unit);
}
}
}
}
memset(szPath, 0x00, sizeof(szPath));
if (SHGetSpecialFolderPathW(NULL, szPath, CSIDL_COMMON_PROGRAMS, false))
{
files.GetFolderInfo(szPath);
for (i=0; i<files.Count(); i++)
{
_GetFileName(files[i]->fullName, FileName);
if (0 == FileName.CompareNoCase(L"Mozilla Firefox.lnk"))
{
if (GetShortcutTarget(files[i]->fullName, Target))
{
unit = new CBrowserList::CBrowserInfo();
unit->m_Name = PTwcsdup(L"Mozilla Firefox");
unit->m_Path = PTwcsdup(Target);
this->m_list.Add(unit);
}
}
else if (0 == FileName.CompareNoCase(L"Waterfox.lnk"))
{
if (GetShortcutTarget(files[i]->fullName, Target))
{
unit = new CBrowserList::CBrowserInfo();
unit->m_Name = PTwcsdup(L"Waterfox");
unit->m_Path = PTwcsdup(Target);
this->m_list.Add(unit);
}
}
else if (0 == FileName.CompareNoCase(L"Navigator.lnk"))
{
if (GetShortcutTarget(files[i]->fullName, Target))
{
unit = new CBrowserList::CBrowserInfo();
unit->m_Name = PTwcsdup(L"Navigator");
unit->m_Path = PTwcsdup(Target);
this->m_list.Add(unit);
}
}
else if (0 == FileName.CompareNoCase(L"Pale Moon.lnk"))
{
if (GetShortcutTarget(files[i]->fullName, Target))
{
unit = new CBrowserList::CBrowserInfo();
unit->m_Name = PTwcsdup(L"Pale Moon");
unit->m_Path = PTwcsdup(Target);
this->m_list.Add(unit);
}
}
else if (0 == FileName.CompareNoCase(L"SeaMonkey.lnk"))
{
if (GetShortcutTarget(files[i]->fullName, Target))
{
unit = new CBrowserList::CBrowserInfo();
unit->m_Name = PTwcsdup(L"SeaMonkey");
unit->m_Path = PTwcsdup(Target);
this->m_list.Add(unit);
}
}
else if (0 == FileName.CompareNoCase(L"Google Chrome.lnk"))
{
if (GetShortcutTarget(files[i]->fullName, Target))
{
unit = new CBrowserList::CBrowserInfo();
unit->m_Name = PTwcsdup(L"Google Chrome");
unit->m_Path = PTwcsdup(Target);
this->m_list.Add(unit);
}
}
else if (0 == FileName.CompareNoCase(L"Safari.lnk"))
{
if (GetShortcutWorkDirectory(files[i]->fullName, Target))
{
unit = new CBrowserList::CBrowserInfo();
unit->m_Name = PTwcsdup(L"Safari");
unit->m_Path = PTwcsdup(Target);
unit->m_Path = PTwcscat(unit->m_Path, L"Safari.exe");
this->m_list.Add(unit);
}
}
else if (0 == FileName.CompareNoCase(L"Opera.lnk"))
{
if (GetShortcutTarget(files[i]->fullName, Target))
{
unit = new CBrowserList::CBrowserInfo();
unit->m_Name = PTwcsdup(L"Opera");
unit->m_Path = PTwcsdup(Target);
this->m_list.Add(unit);
}
}
}
}
6. 呼叫
void openURL(const wchar_t *url)
{
if (g_SettingsInfo.Browser.IsEmpty())
{
ShellExecuteW(NULL, L"open", url, NULL, NULL, SW_SHOWNORMAL);
return;
}
// check Browser was exist
if (FileExists(g_SettingsInfo.Browser.GetString()))
{
ShellExecuteW(NULL, NULL, g_SettingsInfo.Browser.GetString(), url, NULL, SW_SHOWNORMAL);
return;
}
//
ShellExecuteW(NULL, _T("open"), url, NULL, NULL, SW_SHOWNORMAL);
}
libwdi 1.2.4 編譯
OS: Fedora 20
compiler: MinGW
Source: zadig
目前 Spice-gtk 的 USB redirection功能在 windows 下無法作用, 目標將 Spice-gtk 與 libwdi 融合, 讓 windows 下此功能也能運作, 首先讓 libwdi 在 Fedora 下也能編譯(配合 virt-viewer).
1. 建置環境
安裝完 Fedora 完後,安裝 MinGW.
sudo yum install mingw*
2. 設定與編譯
1. 下載 libusb-win32
這邊使用的版本為 libusb-win32-bin-1.2.6.0
2. 下載 libusbK
這邊使用的版本為 libusbK-3.0.5.16-bin
3. 下載 WinDDK 7.1
這邊使用的版本為 7600.16385.1
4. 設定參考路徑
請根據下載檔案的解壓縮位置設定
EX: mingw32-configure --with-ddkdir="/home/jojo/桌面/7600.16385.1" --with-libusb0="/home/jojo/桌面/libusb-win32-bin-1.2.6.0" --with-libusbk="/home/jojo/桌面/libusbK-3.0.5.16-bin/bin"
5. 修改 config.h
修改或新增以下定義
#define COINSTALLER_DIR "wdf"
#define WDF_VER 1009
#define OPT_M64
6. 編譯的時候會說找不到 winusbcoinstaller2.dll
複製 7600.16385.1/redist/winusb/x86/winusbcoinstaller2.dll 到 7600.16385.1/redist/wdf/x86/winusbcoinstaller2.dll
7. 編譯
mingw32-make
8. 安裝
sudo mingw32-make install
9. 產出
在 /usr/i686-w64-mingw32/sys-root/mingw/lib下
libwdi.la
libwdi.a
libwdi.dll.a
在 /usr/i686-w64-mingw32/sys-root/mingw/bin下
libwdi.dll
10. 測試在 libwdi.dll 沒有含 x64 installer, 所以還是拿 windows 下 build 出的 dll 用.
compiler: MinGW
Source: zadig
目前 Spice-gtk 的 USB redirection功能在 windows 下無法作用, 目標將 Spice-gtk 與 libwdi 融合, 讓 windows 下此功能也能運作, 首先讓 libwdi 在 Fedora 下也能編譯(配合 virt-viewer).
1. 建置環境
安裝完 Fedora 完後,安裝 MinGW.
sudo yum install mingw*
2. 設定與編譯
1. 下載 libusb-win32
這邊使用的版本為 libusb-win32-bin-1.2.6.0
2. 下載 libusbK
這邊使用的版本為 libusbK-3.0.5.16-bin
3. 下載 WinDDK 7.1
這邊使用的版本為 7600.16385.1
4. 設定參考路徑
請根據下載檔案的解壓縮位置設定
EX: mingw32-configure --with-ddkdir="/home/jojo/桌面/7600.16385.1" --with-libusb0="/home/jojo/桌面/libusb-win32-bin-1.2.6.0" --with-libusbk="/home/jojo/桌面/libusbK-3.0.5.16-bin/bin"
5. 修改 config.h
修改或新增以下定義
#define COINSTALLER_DIR "wdf"
#define WDF_VER 1009
#define OPT_M64
6. 編譯的時候會說找不到 winusbcoinstaller2.dll
複製 7600.16385.1/redist/winusb/x86/winusbcoinstaller2.dll 到 7600.16385.1/redist/wdf/x86/winusbcoinstaller2.dll
7. 編譯
mingw32-make
8. 安裝
sudo mingw32-make install
9. 產出
在 /usr/i686-w64-mingw32/sys-root/mingw/lib下
libwdi.la
libwdi.a
libwdi.dll.a
在 /usr/i686-w64-mingw32/sys-root/mingw/bin下
libwdi.dll
10. 測試在 libwdi.dll 沒有含 x64 installer, 所以還是拿 windows 下 build 出的 dll 用.
wxPython transparent 一些簡單的透明元件
最近玩 wxPython 3時覺得沒有透明元件覺得就用不下去了, 所以設計了些個簡單的透明元件.
TPanel
TStaticText
TButton
但是寫完之後, 發現還很多元件待寫...等有用到再寫了...囧
#-------------------------------------------------------------------------------
# Name: ExtComponent
# Purpose: simple transparent components for Python 2.7
#
# Author: nanoha
#
# Created: 01/01/3000
# Copyright: (c) nanoha 3000
# Licence: no licence
#-------------------------------------------------------------------------------
import wx
################################################################################
class TPanel(wx.Panel):
def __init__(self, parent, id=-1, image=None, pos=wx.DefaultPosition,
size=wx.DefaultSize, style=wx.TAB_TRAVERSAL, name="panel"):
style |= (wx.CLIP_CHILDREN | wx.TRANSPARENT_WINDOW)
wx.Panel.__init__(self, parent, id, pos, size, style, name)
self.SetBackedImage(image)
self.Bind(wx.EVT_PAINT,self.OnPaint)
self.Bind(wx.EVT_SIZE, self.OnSize)
# 設定背景圖片
def SetBackedImage(self, image=None):
if image is not None:
self.BackedImage = image
tmpImg = self.BackedImage.Copy()
W, H = self.GetClientSize()
tmpImg.Rescale(W, H)
self.BackedBmp = tmpImg.ConvertToBitmap()
else:
self.BackedBmp = None
self.BackedImage = None
self.Refresh()
def OnPaint(self,event):
event.Skip()
(width, height) = self.GetClientSizeTuple()
dc = wx.PaintDC(self)
self.DrawBackedImage(dc, width, height)
def DrawBackedImage(self, dc, width, height):
# 建立繪圖緩衝區
bmp = wx.EmptyBitmap(width, height)
memDC = wx.MemoryDC()
memDC.SelectObject(bmp)
# 塗滿透明色
memDC.SetPen(wx.Pen('#010101'))
memDC.SetBrush(wx.Brush('#010101'))
memDC.DrawRectangle(0, 0, width, height)
# 加入父窗口背景
Parent = self.GetParent()
if Parent:
# 加入父窗口背景色
ParentClr = Parent.GetBackgroundColour()
memDC.SetPen(wx.Pen(ParentClr))
memDC.SetBrush(wx.Brush(ParentClr))
memDC.DrawRectangle(0, 0, width, height)
# 加入父窗口背景圖
if hasattr(Parent, 'BackedBmp'):
if Parent.BackedBmp:
# get position
scr_x,scr_y = self.GetScreenPositionTuple()
x,y = Parent.ScreenToClientXY(scr_x,scr_y)
pbmp_W = Parent.BackedBmp.GetWidth()
pbmp_H = Parent.BackedBmp.GetHeight()
w1 = pbmp_W-x
if width < w1:
w1 = width
h1 = pbmp_H-y
if height < h1:
h1 = height
if w1>0 and h1>0:
pbackDC = wx.MemoryDC(Parent.BackedBmp)
memDC.Blit(0, 0, w1, h1, pbackDC, x, y)
pbackDC.SelectObject(wx.NullBitmap)
# 加入自帶背景
if self.BackedBmp:
bmp_W = self.BackedBmp.GetWidth()
bmp_H = self.BackedBmp.GetHeight()
backDC = wx.MemoryDC(self.BackedBmp)
memDC.Blit(0, 0, bmp_W, bmp_H, backDC, 0, 0)
backDC.SelectObject(wx.NullBitmap)
memDC.SelectObject(wx.NullBitmap)
# 設定透明色
mask = wx.Mask(bmp, wx.Colour(1,1,1))
bmp.SetMask(mask)
# 畫下去
dc.DrawBitmap(bmp, 0, 0, True)
# 將背景圖填滿 panel
def OnSize(self,event):
if self.BackedImage is None:
return
W, H = self.GetClientSize()
if W == 0 or H == 0:
return
bmp_W = self.BackedBmp.GetWidth()
bmp_H = self.BackedBmp.GetHeight()
if W != bmp_W or H != bmp_H:
tmpImg = self.BackedImage.Copy()
tmpImg.Rescale(W, H)
self.BackedBmp = tmpImg.ConvertToBitmap()
self.Refresh()
################################################################################
TST_TEXT_LEFT = 0
TST_TEXT_CENTER = 1
TST_TEXT_RIGHT = 2
class TStaticText(wx.StaticText):
def __init__(self,parent,id,label='',
pos=wx.DefaultPosition,
size=wx.DefaultSize,
style=0,
labelpos=TST_TEXT_LEFT,
name = 'TPStaticText'):
style |= wx.TRANSPARENT_WINDOW
wx.StaticText.__init__(self,parent,id,label,pos,size,style=style)
self.labelpos=labelpos
self.Bind(wx.EVT_PAINT,self.OnPaint)
def OnPaint(self,event):
event.Skip()
(width, height) = self.GetClientSizeTuple()
# 建立繪圖緩衝區
bmp = wx.EmptyBitmap(width, height)
memDC = wx.MemoryDC()
memDC.SelectObject(bmp)
# 塗滿透明色
memDC.SetPen(wx.Pen('#010101'))
memDC.SetBrush(wx.Brush('#010101'))
memDC.DrawRectangle(0, 0, width, height)
# 加入父窗口背景
Parent = self.GetParent()
if Parent:
# 加入父窗口背景色
ParentClr = Parent.GetBackgroundColour()
memDC.SetPen(wx.Pen(ParentClr))
memDC.SetBrush(wx.Brush(ParentClr))
memDC.DrawRectangle(0, 0, width, height)
# 加入父窗口背景圖
if hasattr(Parent, 'BackedBmp'):
if Parent.BackedBmp:
# get position
scr_x,scr_y = self.GetScreenPositionTuple()
x,y = Parent.ScreenToClientXY(scr_x,scr_y)
pbmp_W = Parent.BackedBmp.GetWidth()
pbmp_H = Parent.BackedBmp.GetHeight()
w1 = pbmp_W-x
if width < w1:
w1 = width
h1 = pbmp_H-y
if height < h1:
h1 = height
if w1>0 and h1>0:
pbackDC = wx.MemoryDC(Parent.BackedBmp)
memDC.Blit(0, 0, w1, h1, pbackDC, x, y)
pbackDC.SelectObject(wx.NullBitmap)
# 加入文字
textXpos = textYpos = 0
textWidth, textHeight = self.GetTextExtent(self.GetLabel())
textYpos = (height-textHeight)/2
if self.labelpos == TST_TEXT_CENTER:
textXpos = (width-textWidth)/2
elif self.labelpos == TST_TEXT_RIGHT:
textXpos = width-textWidth
memDC.SetFont(self.GetFont())
#if self.IsEnabled():
memDC.SetTextForeground(self.GetForegroundColour())
#else:
# memDC.SetTextForeground(wx.SystemSettings.GetColour(wx.SYS_COLOUR_GRAYTEXT))
memDC.DrawText(self.GetLabel(), textXpos, textYpos)
memDC.SelectObject(wx.NullBitmap)
# 設定透明色
mask = wx.Mask(bmp, wx.Colour(1,1,1))
bmp.SetMask(mask)
# 畫下去
dc = wx.PaintDC(self)
dc.DrawBitmap(bmp, 0, 0, True)
################################################################################
class TButtonEvent(wx.PyCommandEvent):
def __init__(self, eventType, id):
wx.PyCommandEvent.__init__(self, eventType, id)
self.isDown = False
self.theButton = None
def SetIsDown(self, isDown):
self.isDown = isDown
def GetIsDown(self):
return self.isDown
def SetButtonObj(self, btn):
self.theButton = btn
def GetButtonObj(self):
return self.theButton
################################################################################
TBB_IMAGE_CENTER = 0
TBB_IMAGE_LEFT = 1
TBB_IMAGE_RIGHT = 2
TBB_IMAGE_TOP = 3
TBB_IMAGE_BOTTOM = 4
TBB_LABEL_CENTER = 0
TBB_LABEL_LEFT = 1
TBB_LABEL_RIGHT = 2
TBB_LABEL_TOP = 3
TBB_LABEL_BOTTOM = 4
class TBitmapButton(wx.PyControl):
def __init__(self, parent=None, id=-1, image=None, label='',
pos = wx.DefaultPosition, size = wx.DefaultSize,
style=0, imagepos = TBB_IMAGE_CENTER,
labelpos = TBB_LABEL_CENTER,
validator = wx.DefaultValidator,
name = "Nanohabutton"):
cstyle = style# | wx.BORDER_NONE
wx.PyControl.__init__(self, parent, id, pos, size, cstyle, validator, name)
self.up = True
self.hasFocus = False
self.style = cstyle
if cstyle & wx.BORDER_NONE:
self.bezelWidth = 0
self.useFocusInd = False
else:
self.bezelWidth = 2
self.useFocusInd = True
self.ImagePos = imagepos
self.LabelPos = labelpos
self.BackedBmp = None
if image is not None:
self.BackedBmp = image.ConvertToBitmap()
self.MaskClr = wx.Colour(1,1,1)
self.SetLabel(label)
self.InheritAttributes()
self.SetInitialSize(size)
self.InitColours()
self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
self.Bind(wx.EVT_LEFT_DCLICK, self.OnLeftDown)
self.Bind(wx.EVT_MOTION, self.OnMotion)
self.Bind(wx.EVT_SET_FOCUS, self.OnGainFocus)
self.Bind(wx.EVT_KILL_FOCUS, self.OnLoseFocus)
self.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)
self.Bind(wx.EVT_KEY_UP, self.OnKeyUp)
self.Bind(wx.EVT_PAINT, self.OnPaint)
self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackgound)
self.Bind(wx.EVT_SIZE, self.OnSize)
def SetInitialSize(self, size=None):
if size is None:
size = wx.DefaultSize
wx.PyControl.SetInitialSize(self, size)
SetBestSize = SetInitialSize
def DoGetBestSize(self):
w, h, useMin = self._GetLabelSize()
if self.style & wx.BU_EXACTFIT:
width = w + 2 + 2 * self.bezelWidth + 4 * int(self.useFocusInd)
height = h + 2 + 2 * self.bezelWidth + 4 * int(self.useFocusInd)
else:
defSize = wx.Button.GetDefaultSize()
width = 12 + w
if useMin and width < defSize.width:
width = defSize.width
height = 11 + h
if useMin and height < defSize.height:
height = defSize.height
width = width + self.bezelWidth - 1
height = height + self.bezelWidth - 1
return (width, height)
def AcceptsFocus(self):
return self.IsShown() and self.IsEnabled()
def GetDefaultAttributes(self):
return wx.Button.GetClassDefaultAttributes()
def ShouldInheritColours(self):
return False
def Enable(self, enable=True):
if enable != self.IsEnabled():
wx.PyControl.Enable(self, enable)
self.Refresh()
def SetBezelWidth(self, width):
self.bezelWidth = width
def GetBezelWidth(self):
return self.bezelWidth
def SetUseFocusIndicator(self, flag):
self.useFocusInd = flag
def GetUseFocusIndicator(self):
return self.useFocusInd
def InitColours(self):
faceClr = self.GetBackgroundColour()
r, g, b = faceClr.Get()
fr, fg, fb = min(255,r+32), min(255,g+32), min(255,b+32)
self.faceDnClr = wx.Colour(fr, fg, fb)
sr, sg, sb = max(0,r-32), max(0,g-32), max(0,b-32)
self.shadowPenClr = wx.Colour(sr,sg,sb)
hr, hg, hb = min(255,r+64), min(255,g+64), min(255,b+64)
self.highlightPenClr = wx.Colour(hr,hg,hb)
self.focusClr = wx.Colour(hr, hg, hb)
def SetBackgroundColour(self, colour):
wx.PyControl.SetBackgroundColour(self, colour)
self.InitColours()
def SetForegroundColour(self, colour):
wx.PyControl.SetForegroundColour(self, colour)
self.InitColours()
def SetDefault(self):
tlw = wx.GetTopLevelParent(self)
if hasattr(tlw, 'SetDefaultItem'):
tlw.SetDefaultItem(self)
def _GetLabelSize(self):
w, h = self.GetTextExtent(self.GetLabel())
if not self.BackedBmp:
return w, h, True
w_bmp = self.BackedBmp.GetWidth() + 2
h_bmp = self.BackedBmp.GetHeight() + 2
height = h + h_bmp + 12
if w_bmp > w:
width = w_bmp
else:
width = w
return width, height, True
def Notify(self):
evt = ExtButtonEvent(wx.wxEVT_COMMAND_BUTTON_CLICKED, self.GetId())
evt.SetIsDown(not self.up)
evt.SetButtonObj(self)
evt.SetEventObject(self)
self.GetEventHandler().ProcessEvent(evt)
def DrawBezel(self, dc, x1, y1, x2, y2):
# draw the upper left sides
if self.up:
dc.SetPen(wx.Pen(self.highlightPenClr, 1, wx.SOLID))
else:
dc.SetPen(wx.Pen(self.shadowPenClr, 1, wx.SOLID))
for i in range(self.bezelWidth):
dc.DrawLine(x1+i, y1, x1+i, y2-i)
dc.DrawLine(x1, y1+i, x2-i, y1+i)
# draw the lower right sides
if self.up:
dc.SetPen(wx.Pen(self.shadowPenClr, 1, wx.SOLID))
else:
dc.SetPen(wx.Pen(self.highlightPenClr, 1, wx.SOLID))
for i in range(self.bezelWidth):
dc.DrawLine(x1+i, y2-i, x2+1, y2-i)
dc.DrawLine(x2-i, y1+i, x2-i, y2)
def DrawBackedImage(self, dc, width, height, dx=0, dy=0):
x1 = y1 = 0
# 建立繪圖緩衝區
bmp = wx.EmptyBitmap(width, height)
memDC = wx.MemoryDC()
memDC.SelectObject(bmp)
# 塗滿透明色
memDC.SetPen(wx.Pen(self.MaskClr))
memDC.SetBrush(wx.Brush(self.MaskClr))
memDC.DrawRectangle(0, 0, width, height)
# 加入父窗口背景
Parent = self.GetParent()
if Parent:
# 加入父窗口背景色
ParentClr = Parent.GetBackgroundColour()
memDC.SetPen(wx.Pen(ParentClr))
memDC.SetBrush(wx.Brush(ParentClr))
memDC.DrawRectangle(0, 0, width, height)
# 加入父窗口背景圖
if hasattr(Parent, 'BackedBmp'):
if Parent.BackedBmp:
# get position
scr_x,scr_y = self.GetScreenPositionTuple()
x,y = Parent.ScreenToClientXY(scr_x,scr_y)
pbmp_W = Parent.BackedBmp.GetWidth()
pbmp_H = Parent.BackedBmp.GetHeight()
w1 = pbmp_W-x
if width < w1:
w1 = width
h1 = pbmp_H-y
if height < h1:
h1 = height
if w1>0 and h1>0:
pbackDC = wx.MemoryDC(Parent.BackedBmp)
memDC.Blit(0, 0, w1, h1, pbackDC, x, y)
pbackDC.SelectObject(wx.NullBitmap)
# 加入自帶背景
if self.BackedBmp:
bmp_W = self.BackedBmp.GetWidth()
bmp_H = self.BackedBmp.GetHeight()
backDC = wx.MemoryDC(self.BackedBmp)
# 背景位置
if TBB_IMAGE_LEFT == self.ImagePos:
x1 = dx
y1 = (height-bmp_H)/2+dy
elif TBB_IMAGE_RIGHT == self.ImagePos:
x1 = width-bmp_W+dx
y1 = (height-bmp_H)/2+dy
elif TBB_IMAGE_TOP == self.ImagePos:
x1 = (width-bmp_W)/2+dx
y1 = dy
elif TBB_IMAGE_BOTTOM == self.ImagePos:
x1 = (width-bmp_W)/2+dx
y1 = height-bmp_H+dy
else:
x1 = (width-bmp_W)/2+dx
y1 = (height-bmp_H)/2+dy
memDC.Blit(x1, y1, bmp_W, bmp_H, backDC, 0, 0)
backDC.SelectObject(wx.NullBitmap)
self.DrawBackedImage2(memDC, dx, dy)
# 邊框
x1 = y1 = 0
x2 = width-1
y2 = height-1
self.DrawBezel(memDC, x1, y1, x2, y2)
# 加入文字
memDC.SetFont(self.GetFont())
if self.IsEnabled():
memDC.SetTextForeground(self.GetForegroundColour())
else:
memDC.SetTextForeground(wx.SystemSettings.GetColour(wx.SYS_COLOUR_GRAYTEXT))
label = self.GetLabel()
tw, th = memDC.GetTextExtent(label)
# 文字位置
if TBB_LABEL_LEFT == self.LabelPos:
x1 = dx
y1 = (height-th)/2+dy
elif TBB_LABEL_RIGHT == self.LabelPos:
x1 = width-tw+dx
y1 = (height-th)/2+dy
elif TBB_LABEL_TOP == self.LabelPos:
x1 = (width-tw)/2+dx
y1 = dy
elif TBB_LABEL_BOTTOM == self.LabelPos:
x1 = (width-tw)/2+dx
y1 = height-th+dy
else:
x1 = (width-tw)/2+dx
y1 = (height-th)/2+dy
memDC.DrawText(label, x1, y1)
# 加入Focus效果
if self.hasFocus and self.useFocusInd:
self.DrawFocusIndicator(memDC, width, height)
memDC.SelectObject(wx.NullBitmap)
# 設定透明色
mask = wx.Mask(bmp, self.MaskClr)
bmp.SetMask(mask)
# 畫下去
hasMask = bmp.GetMask() is not None
dc.DrawBitmap(bmp, 0, 0, hasMask)
def DrawBackedImage2(self, dc, dx=0, dy=0):
pass
def DrawFocusIndicator(self, dc, w, h):
bw = self.bezelWidth
textClr = self.GetForegroundColour()
focusIndPen = wx.Pen(textClr, 1, wx.USER_DASH)
focusIndPen.SetDashes([1,1])
focusIndPen.SetCap(wx.CAP_BUTT)
if wx.Platform == "__WXMAC__":
dc.SetLogicalFunction(wx.XOR)
else:
focusIndPen.SetColour(self.focusClr)
dc.SetLogicalFunction(wx.INVERT)
dc.SetPen(focusIndPen)
dc.SetBrush(wx.TRANSPARENT_BRUSH)
dc.DrawRectangle(bw+2,bw+2, w-bw*2-4, h-bw*2-4)
dc.SetLogicalFunction(wx.COPY)
def OnPaint(self, event):
(width, height) = self.GetClientSizeTuple()
dx = dy = 0
if not self.up:
dx = dy = 1
dc = wx.PaintDC(self)
#dc.SetBackground(wx.TRANSPARENT_BRUSH)
#dc.Clear()
self.DrawBackedImage(dc, width, height, dx, dy)
def OnSize(self, event):
self.Refresh()
event.Skip()
def OnEraseBackgound(self, event):
pass
def OnLeftDown(self, event):
if not self.IsEnabled():
return
self.up = False
self.CaptureMouse()
self.SetFocus()
self.Refresh()
event.Skip()
def OnLeftUp(self, event):
if not self.IsEnabled() or not self.HasCapture():
return
if self.HasCapture():
self.ReleaseMouse()
if not self.up: # if the button was down when the mouse was released...
self.Notify()
self.up = True
if self: # in case the button was destroyed in the eventhandler
self.Refresh()
event.Skip()
def OnMotion(self, event):
if not self.IsEnabled() or not self.HasCapture():
return
if event.LeftIsDown() and self.HasCapture():
x,y = event.GetPositionTuple()
w,h = self.GetClientSizeTuple()
if self.up and x<w and x>=0 and y<h and y>=0:
self.up = False
self.Refresh()
return
if not self.up and (x<0 or y<0 or x>=w or y>=h):
self.up = True
self.Refresh()
return
event.Skip()
def OnGainFocus(self, event):
self.hasFocus = True
self.Refresh()
self.Update()
def OnLoseFocus(self, event):
self.hasFocus = False
self.Refresh()
self.Update()
def OnKeyDown(self, event):
if self.hasFocus and event.GetKeyCode() == ord(" "):
self.up = False
self.Refresh()
event.Skip()
def OnKeyUp(self, event):
if self.hasFocus and event.GetKeyCode() == ord(" "):
self.up = True
self.Notify()
self.Refresh()
event.Skip()
################################################################################
TPanel
TStaticText
TButton
但是寫完之後, 發現還很多元件待寫...等有用到再寫了...囧
#-------------------------------------------------------------------------------
# Name: ExtComponent
# Purpose: simple transparent components for Python 2.7
#
# Author: nanoha
#
# Created: 01/01/3000
# Copyright: (c) nanoha 3000
# Licence: no licence
#-------------------------------------------------------------------------------
import wx
################################################################################
class TPanel(wx.Panel):
def __init__(self, parent, id=-1, image=None, pos=wx.DefaultPosition,
size=wx.DefaultSize, style=wx.TAB_TRAVERSAL, name="panel"):
style |= (wx.CLIP_CHILDREN | wx.TRANSPARENT_WINDOW)
wx.Panel.__init__(self, parent, id, pos, size, style, name)
self.SetBackedImage(image)
self.Bind(wx.EVT_PAINT,self.OnPaint)
self.Bind(wx.EVT_SIZE, self.OnSize)
# 設定背景圖片
def SetBackedImage(self, image=None):
if image is not None:
self.BackedImage = image
tmpImg = self.BackedImage.Copy()
W, H = self.GetClientSize()
tmpImg.Rescale(W, H)
self.BackedBmp = tmpImg.ConvertToBitmap()
else:
self.BackedBmp = None
self.BackedImage = None
self.Refresh()
def OnPaint(self,event):
event.Skip()
(width, height) = self.GetClientSizeTuple()
dc = wx.PaintDC(self)
self.DrawBackedImage(dc, width, height)
def DrawBackedImage(self, dc, width, height):
# 建立繪圖緩衝區
bmp = wx.EmptyBitmap(width, height)
memDC = wx.MemoryDC()
memDC.SelectObject(bmp)
# 塗滿透明色
memDC.SetPen(wx.Pen('#010101'))
memDC.SetBrush(wx.Brush('#010101'))
memDC.DrawRectangle(0, 0, width, height)
# 加入父窗口背景
Parent = self.GetParent()
if Parent:
# 加入父窗口背景色
ParentClr = Parent.GetBackgroundColour()
memDC.SetPen(wx.Pen(ParentClr))
memDC.SetBrush(wx.Brush(ParentClr))
memDC.DrawRectangle(0, 0, width, height)
# 加入父窗口背景圖
if hasattr(Parent, 'BackedBmp'):
if Parent.BackedBmp:
# get position
scr_x,scr_y = self.GetScreenPositionTuple()
x,y = Parent.ScreenToClientXY(scr_x,scr_y)
pbmp_W = Parent.BackedBmp.GetWidth()
pbmp_H = Parent.BackedBmp.GetHeight()
w1 = pbmp_W-x
if width < w1:
w1 = width
h1 = pbmp_H-y
if height < h1:
h1 = height
if w1>0 and h1>0:
pbackDC = wx.MemoryDC(Parent.BackedBmp)
memDC.Blit(0, 0, w1, h1, pbackDC, x, y)
pbackDC.SelectObject(wx.NullBitmap)
# 加入自帶背景
if self.BackedBmp:
bmp_W = self.BackedBmp.GetWidth()
bmp_H = self.BackedBmp.GetHeight()
backDC = wx.MemoryDC(self.BackedBmp)
memDC.Blit(0, 0, bmp_W, bmp_H, backDC, 0, 0)
backDC.SelectObject(wx.NullBitmap)
memDC.SelectObject(wx.NullBitmap)
# 設定透明色
mask = wx.Mask(bmp, wx.Colour(1,1,1))
bmp.SetMask(mask)
# 畫下去
dc.DrawBitmap(bmp, 0, 0, True)
# 將背景圖填滿 panel
def OnSize(self,event):
if self.BackedImage is None:
return
W, H = self.GetClientSize()
if W == 0 or H == 0:
return
bmp_W = self.BackedBmp.GetWidth()
bmp_H = self.BackedBmp.GetHeight()
if W != bmp_W or H != bmp_H:
tmpImg = self.BackedImage.Copy()
tmpImg.Rescale(W, H)
self.BackedBmp = tmpImg.ConvertToBitmap()
self.Refresh()
################################################################################
TST_TEXT_LEFT = 0
TST_TEXT_CENTER = 1
TST_TEXT_RIGHT = 2
class TStaticText(wx.StaticText):
def __init__(self,parent,id,label='',
pos=wx.DefaultPosition,
size=wx.DefaultSize,
style=0,
labelpos=TST_TEXT_LEFT,
name = 'TPStaticText'):
style |= wx.TRANSPARENT_WINDOW
wx.StaticText.__init__(self,parent,id,label,pos,size,style=style)
self.labelpos=labelpos
self.Bind(wx.EVT_PAINT,self.OnPaint)
def OnPaint(self,event):
event.Skip()
(width, height) = self.GetClientSizeTuple()
# 建立繪圖緩衝區
bmp = wx.EmptyBitmap(width, height)
memDC = wx.MemoryDC()
memDC.SelectObject(bmp)
# 塗滿透明色
memDC.SetPen(wx.Pen('#010101'))
memDC.SetBrush(wx.Brush('#010101'))
memDC.DrawRectangle(0, 0, width, height)
# 加入父窗口背景
Parent = self.GetParent()
if Parent:
# 加入父窗口背景色
ParentClr = Parent.GetBackgroundColour()
memDC.SetPen(wx.Pen(ParentClr))
memDC.SetBrush(wx.Brush(ParentClr))
memDC.DrawRectangle(0, 0, width, height)
# 加入父窗口背景圖
if hasattr(Parent, 'BackedBmp'):
if Parent.BackedBmp:
# get position
scr_x,scr_y = self.GetScreenPositionTuple()
x,y = Parent.ScreenToClientXY(scr_x,scr_y)
pbmp_W = Parent.BackedBmp.GetWidth()
pbmp_H = Parent.BackedBmp.GetHeight()
w1 = pbmp_W-x
if width < w1:
w1 = width
h1 = pbmp_H-y
if height < h1:
h1 = height
if w1>0 and h1>0:
pbackDC = wx.MemoryDC(Parent.BackedBmp)
memDC.Blit(0, 0, w1, h1, pbackDC, x, y)
pbackDC.SelectObject(wx.NullBitmap)
# 加入文字
textXpos = textYpos = 0
textWidth, textHeight = self.GetTextExtent(self.GetLabel())
textYpos = (height-textHeight)/2
if self.labelpos == TST_TEXT_CENTER:
textXpos = (width-textWidth)/2
elif self.labelpos == TST_TEXT_RIGHT:
textXpos = width-textWidth
memDC.SetFont(self.GetFont())
#if self.IsEnabled():
memDC.SetTextForeground(self.GetForegroundColour())
#else:
# memDC.SetTextForeground(wx.SystemSettings.GetColour(wx.SYS_COLOUR_GRAYTEXT))
memDC.DrawText(self.GetLabel(), textXpos, textYpos)
memDC.SelectObject(wx.NullBitmap)
# 設定透明色
mask = wx.Mask(bmp, wx.Colour(1,1,1))
bmp.SetMask(mask)
# 畫下去
dc = wx.PaintDC(self)
dc.DrawBitmap(bmp, 0, 0, True)
################################################################################
class TButtonEvent(wx.PyCommandEvent):
def __init__(self, eventType, id):
wx.PyCommandEvent.__init__(self, eventType, id)
self.isDown = False
self.theButton = None
def SetIsDown(self, isDown):
self.isDown = isDown
def GetIsDown(self):
return self.isDown
def SetButtonObj(self, btn):
self.theButton = btn
def GetButtonObj(self):
return self.theButton
################################################################################
TBB_IMAGE_CENTER = 0
TBB_IMAGE_LEFT = 1
TBB_IMAGE_RIGHT = 2
TBB_IMAGE_TOP = 3
TBB_IMAGE_BOTTOM = 4
TBB_LABEL_CENTER = 0
TBB_LABEL_LEFT = 1
TBB_LABEL_RIGHT = 2
TBB_LABEL_TOP = 3
TBB_LABEL_BOTTOM = 4
class TBitmapButton(wx.PyControl):
def __init__(self, parent=None, id=-1, image=None, label='',
pos = wx.DefaultPosition, size = wx.DefaultSize,
style=0, imagepos = TBB_IMAGE_CENTER,
labelpos = TBB_LABEL_CENTER,
validator = wx.DefaultValidator,
name = "Nanohabutton"):
cstyle = style# | wx.BORDER_NONE
wx.PyControl.__init__(self, parent, id, pos, size, cstyle, validator, name)
self.up = True
self.hasFocus = False
self.style = cstyle
if cstyle & wx.BORDER_NONE:
self.bezelWidth = 0
self.useFocusInd = False
else:
self.bezelWidth = 2
self.useFocusInd = True
self.ImagePos = imagepos
self.LabelPos = labelpos
self.BackedBmp = None
if image is not None:
self.BackedBmp = image.ConvertToBitmap()
self.MaskClr = wx.Colour(1,1,1)
self.SetLabel(label)
self.InheritAttributes()
self.SetInitialSize(size)
self.InitColours()
self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
self.Bind(wx.EVT_LEFT_DCLICK, self.OnLeftDown)
self.Bind(wx.EVT_MOTION, self.OnMotion)
self.Bind(wx.EVT_SET_FOCUS, self.OnGainFocus)
self.Bind(wx.EVT_KILL_FOCUS, self.OnLoseFocus)
self.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)
self.Bind(wx.EVT_KEY_UP, self.OnKeyUp)
self.Bind(wx.EVT_PAINT, self.OnPaint)
self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackgound)
self.Bind(wx.EVT_SIZE, self.OnSize)
def SetInitialSize(self, size=None):
if size is None:
size = wx.DefaultSize
wx.PyControl.SetInitialSize(self, size)
SetBestSize = SetInitialSize
def DoGetBestSize(self):
w, h, useMin = self._GetLabelSize()
if self.style & wx.BU_EXACTFIT:
width = w + 2 + 2 * self.bezelWidth + 4 * int(self.useFocusInd)
height = h + 2 + 2 * self.bezelWidth + 4 * int(self.useFocusInd)
else:
defSize = wx.Button.GetDefaultSize()
width = 12 + w
if useMin and width < defSize.width:
width = defSize.width
height = 11 + h
if useMin and height < defSize.height:
height = defSize.height
width = width + self.bezelWidth - 1
height = height + self.bezelWidth - 1
return (width, height)
def AcceptsFocus(self):
return self.IsShown() and self.IsEnabled()
def GetDefaultAttributes(self):
return wx.Button.GetClassDefaultAttributes()
def ShouldInheritColours(self):
return False
def Enable(self, enable=True):
if enable != self.IsEnabled():
wx.PyControl.Enable(self, enable)
self.Refresh()
def SetBezelWidth(self, width):
self.bezelWidth = width
def GetBezelWidth(self):
return self.bezelWidth
def SetUseFocusIndicator(self, flag):
self.useFocusInd = flag
def GetUseFocusIndicator(self):
return self.useFocusInd
def InitColours(self):
faceClr = self.GetBackgroundColour()
r, g, b = faceClr.Get()
fr, fg, fb = min(255,r+32), min(255,g+32), min(255,b+32)
self.faceDnClr = wx.Colour(fr, fg, fb)
sr, sg, sb = max(0,r-32), max(0,g-32), max(0,b-32)
self.shadowPenClr = wx.Colour(sr,sg,sb)
hr, hg, hb = min(255,r+64), min(255,g+64), min(255,b+64)
self.highlightPenClr = wx.Colour(hr,hg,hb)
self.focusClr = wx.Colour(hr, hg, hb)
def SetBackgroundColour(self, colour):
wx.PyControl.SetBackgroundColour(self, colour)
self.InitColours()
def SetForegroundColour(self, colour):
wx.PyControl.SetForegroundColour(self, colour)
self.InitColours()
def SetDefault(self):
tlw = wx.GetTopLevelParent(self)
if hasattr(tlw, 'SetDefaultItem'):
tlw.SetDefaultItem(self)
def _GetLabelSize(self):
w, h = self.GetTextExtent(self.GetLabel())
if not self.BackedBmp:
return w, h, True
w_bmp = self.BackedBmp.GetWidth() + 2
h_bmp = self.BackedBmp.GetHeight() + 2
height = h + h_bmp + 12
if w_bmp > w:
width = w_bmp
else:
width = w
return width, height, True
def Notify(self):
evt = ExtButtonEvent(wx.wxEVT_COMMAND_BUTTON_CLICKED, self.GetId())
evt.SetIsDown(not self.up)
evt.SetButtonObj(self)
evt.SetEventObject(self)
self.GetEventHandler().ProcessEvent(evt)
def DrawBezel(self, dc, x1, y1, x2, y2):
# draw the upper left sides
if self.up:
dc.SetPen(wx.Pen(self.highlightPenClr, 1, wx.SOLID))
else:
dc.SetPen(wx.Pen(self.shadowPenClr, 1, wx.SOLID))
for i in range(self.bezelWidth):
dc.DrawLine(x1+i, y1, x1+i, y2-i)
dc.DrawLine(x1, y1+i, x2-i, y1+i)
# draw the lower right sides
if self.up:
dc.SetPen(wx.Pen(self.shadowPenClr, 1, wx.SOLID))
else:
dc.SetPen(wx.Pen(self.highlightPenClr, 1, wx.SOLID))
for i in range(self.bezelWidth):
dc.DrawLine(x1+i, y2-i, x2+1, y2-i)
dc.DrawLine(x2-i, y1+i, x2-i, y2)
def DrawBackedImage(self, dc, width, height, dx=0, dy=0):
x1 = y1 = 0
# 建立繪圖緩衝區
bmp = wx.EmptyBitmap(width, height)
memDC = wx.MemoryDC()
memDC.SelectObject(bmp)
# 塗滿透明色
memDC.SetPen(wx.Pen(self.MaskClr))
memDC.SetBrush(wx.Brush(self.MaskClr))
memDC.DrawRectangle(0, 0, width, height)
# 加入父窗口背景
Parent = self.GetParent()
if Parent:
# 加入父窗口背景色
ParentClr = Parent.GetBackgroundColour()
memDC.SetPen(wx.Pen(ParentClr))
memDC.SetBrush(wx.Brush(ParentClr))
memDC.DrawRectangle(0, 0, width, height)
# 加入父窗口背景圖
if hasattr(Parent, 'BackedBmp'):
if Parent.BackedBmp:
# get position
scr_x,scr_y = self.GetScreenPositionTuple()
x,y = Parent.ScreenToClientXY(scr_x,scr_y)
pbmp_W = Parent.BackedBmp.GetWidth()
pbmp_H = Parent.BackedBmp.GetHeight()
w1 = pbmp_W-x
if width < w1:
w1 = width
h1 = pbmp_H-y
if height < h1:
h1 = height
if w1>0 and h1>0:
pbackDC = wx.MemoryDC(Parent.BackedBmp)
memDC.Blit(0, 0, w1, h1, pbackDC, x, y)
pbackDC.SelectObject(wx.NullBitmap)
# 加入自帶背景
if self.BackedBmp:
bmp_W = self.BackedBmp.GetWidth()
bmp_H = self.BackedBmp.GetHeight()
backDC = wx.MemoryDC(self.BackedBmp)
# 背景位置
if TBB_IMAGE_LEFT == self.ImagePos:
x1 = dx
y1 = (height-bmp_H)/2+dy
elif TBB_IMAGE_RIGHT == self.ImagePos:
x1 = width-bmp_W+dx
y1 = (height-bmp_H)/2+dy
elif TBB_IMAGE_TOP == self.ImagePos:
x1 = (width-bmp_W)/2+dx
y1 = dy
elif TBB_IMAGE_BOTTOM == self.ImagePos:
x1 = (width-bmp_W)/2+dx
y1 = height-bmp_H+dy
else:
x1 = (width-bmp_W)/2+dx
y1 = (height-bmp_H)/2+dy
memDC.Blit(x1, y1, bmp_W, bmp_H, backDC, 0, 0)
backDC.SelectObject(wx.NullBitmap)
self.DrawBackedImage2(memDC, dx, dy)
# 邊框
x1 = y1 = 0
x2 = width-1
y2 = height-1
self.DrawBezel(memDC, x1, y1, x2, y2)
# 加入文字
memDC.SetFont(self.GetFont())
if self.IsEnabled():
memDC.SetTextForeground(self.GetForegroundColour())
else:
memDC.SetTextForeground(wx.SystemSettings.GetColour(wx.SYS_COLOUR_GRAYTEXT))
label = self.GetLabel()
tw, th = memDC.GetTextExtent(label)
# 文字位置
if TBB_LABEL_LEFT == self.LabelPos:
x1 = dx
y1 = (height-th)/2+dy
elif TBB_LABEL_RIGHT == self.LabelPos:
x1 = width-tw+dx
y1 = (height-th)/2+dy
elif TBB_LABEL_TOP == self.LabelPos:
x1 = (width-tw)/2+dx
y1 = dy
elif TBB_LABEL_BOTTOM == self.LabelPos:
x1 = (width-tw)/2+dx
y1 = height-th+dy
else:
x1 = (width-tw)/2+dx
y1 = (height-th)/2+dy
memDC.DrawText(label, x1, y1)
# 加入Focus效果
if self.hasFocus and self.useFocusInd:
self.DrawFocusIndicator(memDC, width, height)
memDC.SelectObject(wx.NullBitmap)
# 設定透明色
mask = wx.Mask(bmp, self.MaskClr)
bmp.SetMask(mask)
# 畫下去
hasMask = bmp.GetMask() is not None
dc.DrawBitmap(bmp, 0, 0, hasMask)
def DrawBackedImage2(self, dc, dx=0, dy=0):
pass
def DrawFocusIndicator(self, dc, w, h):
bw = self.bezelWidth
textClr = self.GetForegroundColour()
focusIndPen = wx.Pen(textClr, 1, wx.USER_DASH)
focusIndPen.SetDashes([1,1])
focusIndPen.SetCap(wx.CAP_BUTT)
if wx.Platform == "__WXMAC__":
dc.SetLogicalFunction(wx.XOR)
else:
focusIndPen.SetColour(self.focusClr)
dc.SetLogicalFunction(wx.INVERT)
dc.SetPen(focusIndPen)
dc.SetBrush(wx.TRANSPARENT_BRUSH)
dc.DrawRectangle(bw+2,bw+2, w-bw*2-4, h-bw*2-4)
dc.SetLogicalFunction(wx.COPY)
def OnPaint(self, event):
(width, height) = self.GetClientSizeTuple()
dx = dy = 0
if not self.up:
dx = dy = 1
dc = wx.PaintDC(self)
#dc.SetBackground(wx.TRANSPARENT_BRUSH)
#dc.Clear()
self.DrawBackedImage(dc, width, height, dx, dy)
def OnSize(self, event):
self.Refresh()
event.Skip()
def OnEraseBackgound(self, event):
pass
def OnLeftDown(self, event):
if not self.IsEnabled():
return
self.up = False
self.CaptureMouse()
self.SetFocus()
self.Refresh()
event.Skip()
def OnLeftUp(self, event):
if not self.IsEnabled() or not self.HasCapture():
return
if self.HasCapture():
self.ReleaseMouse()
if not self.up: # if the button was down when the mouse was released...
self.Notify()
self.up = True
if self: # in case the button was destroyed in the eventhandler
self.Refresh()
event.Skip()
def OnMotion(self, event):
if not self.IsEnabled() or not self.HasCapture():
return
if event.LeftIsDown() and self.HasCapture():
x,y = event.GetPositionTuple()
w,h = self.GetClientSizeTuple()
if self.up and x<w and x>=0 and y<h and y>=0:
self.up = False
self.Refresh()
return
if not self.up and (x<0 or y<0 or x>=w or y>=h):
self.up = True
self.Refresh()
return
event.Skip()
def OnGainFocus(self, event):
self.hasFocus = True
self.Refresh()
self.Update()
def OnLoseFocus(self, event):
self.hasFocus = False
self.Refresh()
self.Update()
def OnKeyDown(self, event):
if self.hasFocus and event.GetKeyCode() == ord(" "):
self.up = False
self.Refresh()
event.Skip()
def OnKeyUp(self, event):
if self.hasFocus and event.GetKeyCode() == ord(" "):
self.up = True
self.Notify()
self.Refresh()
event.Skip()
################################################################################
訂閱:
文章 (Atom)