1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
# coding: big5
from ctypes import *

version = '0.1.2'

STD_INPUT_HANDLE	= -10
STD_OUTPUT_HANDLE	= -11
STD_ERROR_HANDLE	= -12

# Attribute constants
FOREGROUND_BLUE      		= 0x0001 # text color contains blue.
FOREGROUND_GREEN     		= 0x0002 # text color contains green.
FOREGROUND_RED       		= 0x0004 # text color contains red.
FOREGROUND_WHITE			= FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED
FOREGROUND_INTENSITY 		= 0x0008 # text color is intensified.
BACKGROUND_BLUE      		= 0x0010 # background color contains blue.
BACKGROUND_GREEN     		= 0x0020 # background color contains green.
BACKGROUND_RED       		= 0x0040 # background color contains red.
BACKGROUND_WHITE			= BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED
BACKGROUND_INTENSITY 		= 0x0080 # background color is intensified.
COMMON_LVB_LEADING_BYTE    	= 0x0100 # Leading Byte of DBCS
COMMON_LVB_TRAILING_BYTE   	= 0x0200 # Trailing Byte of DBCS
COMMON_LVB_GRID_HORIZONTAL 	= 0x0400 # DBCS: Grid attribute: top horizontal.
COMMON_LVB_GRID_LVERTICAL  	= 0x0800 # DBCS: Grid attribute: left vertical.
COMMON_LVB_GRID_RVERTICAL  	= 0x1000 # DBCS: Grid attribute: right vertical.
COMMON_LVB_REVERSE_VIDEO   	= 0x4000 # DBCS: Reverse fore/back ground attribute.
COMMON_LVB_UNDERSCORE      	= 0x8000 # DBCS: Underscore.

class COORD(Structure):
	_fields_ = [
		('x', c_short),
		('y', c_short),
	]

class SmallRect(Structure):
	_fields_ = [
		('left', c_short),
		('top', c_short),
		('right', c_short),
		('bottom', c_short),
	]

class ConsoleScreenBufferInfo(Structure):
	_fields_ = [
		('size', COORD),
		('cursorPos', COORD),
		('attributes', c_ushort),
		('window', SmallRect),
		('maxWindowSize', COORD),
	]


GetStdHandle = windll.kernel32.GetStdHandle
SetConsoleCursorPosition = windll.kernel32.SetConsoleCursorPosition
SetConsoleTextAttribute = windll.kernel32.SetConsoleTextAttribute
GetConsoleScreenBufferInfo = windll.kernel32.GetConsoleScreenBufferInfo
FillConsoleOutputCharacter = windll.kernel32.FillConsoleOutputCharacterA
FillConsoleOutputAttribute = windll.kernel32.FillConsoleOutputAttribute


def clear_screen():
	coordScreen = COORD(0, 0)
	info = ConsoleScreenBufferInfo()
	h = GetStdHandle(STD_OUTPUT_HANDLE)
	GetConsoleScreenBufferInfo(h, byref(info))
	conSize = info.size.x * info.size.y
	charWritten = c_long(0)
	FillConsoleOutputCharacter(h, c_char(' '), conSize, coordScreen, byref(charWritten))
	GetConsoleScreenBufferInfo(h, byref(info))
	FillConsoleOutputAttribute(h, info.attributes, conSize, coordScreen, byref(charWritten))
	SetConsoleCursorPosition(h, coordScreen)


def move_cursor(x=0, y=0):
	h = GetStdHandle(STD_OUTPUT_HANDLE)
	SetConsoleCursorPosition(h, COORD(x, y))


def cursor_position():
	h = GetStdHandle(STD_OUTPUT_HANDLE)
	info = ConsoleScreenBufferInfo()
	GetConsoleScreenBufferInfo(h, byref(info))
	return info.cursorPos.x, info.cursorPos.y


def color_print(attr, fmt, *args):
	"""
	color_print is equivalent to:
		print fmt % args (if fmt endswith [newline])
		print fmt % args, (if fmt not endswith [newline])

	Note:
	    There is no space between the output of two successive color_print
	    operation(if fmt not endswith [newline]). This behavior is different
	    from Python's print statement.
	"""
	h = GetStdHandle(STD_OUTPUT_HANDLE)
	info = ConsoleScreenBufferInfo()
	try:
		SetConsoleTextAttribute(h, attr & 0xFFFF)
		GetConsoleScreenBufferInfo(h, byref(info))
		s = fmt % args
		print s
		if s[-1] != '\n':
			newX, newY = info.cursorPos.x + len(s), info.cursorPos.y
			if newX > info.size.x:
				newX, newY = newX % info.size.x, newY + 1
			move_cursor(newX, newY)
	finally:
		SetConsoleTextAttribute(h, FOREGROUND_WHITE)


def getch():
	"""
	Perform key detection.
	Returns:
	    1. A normal key, ex: 'A'(return string with length 1)
	    2. A control key, ex: F1(return tuple as (0, scancode) or (0xE0, scancode)
	    3. A multi-bytes character, ex: '\xb5\xd8'(return string with length 2)
	"""
	_getch = windll.msvcrt._getch
	ch = _getch()
	if ch in (0, 0xE0): # control key
		return ch, _getch()
	elif ch > 127: # MBCS character
		return chr(ch) + chr(_getch())
	else:
		return chr(ch)


def main():
	u"""Just a demo. No matter what you see, don't panic!!!"""
	import time
	move_cursor(0, 20)
	color_print(BACKGROUND_WHITE | FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_BLUE,
		main.__doc__)
	for x in xrange(1, 101):
		move_cursor(30, 10)
		color_print(FOREGROUND_INTENSITY | FOREGROUND_GREEN, 'Format Disk:')
		color_print(BACKGROUND_RED | BACKGROUND_INTENSITY, '%d%%', x)
		time.sleep(0.3)



if __name__ == '__main__':
	main()