CS 325 - PowerPoint PPT Presentation

1 / 47
About This Presentation
Title:

CS 325

Description:

Make a hollow square of elephants. Look for images ... For multiple bitmaps, you only need multiple CDC's... Provide a finite time for the user to respond ... – PowerPoint PPT presentation

Number of Views:45
Avg rating:3.0/5.0
Slides: 48
Provided by: dyes
Category:
Tags: study | time

less

Transcript and Presenter's Notes

Title: CS 325


1
CS 325
  • Unix Programming Environment
  • and
  • Windows Programming
  • with Microsoft Foundation Classes (MFC)

2
Announcements
  • Advising for Summer and Fall pre-registration
    begins this week
  • We are offering CS 325 (Software Development and
    Systems) and CS 357 (Data Structures) in both
    Summer and Fall
  • Enrollments for both 325 and 357 requires at
    least 10 students.  Otherwise these courses may
    be cancelled and there will be fewer available
    courses this summer.  The decision may be made
    after pre-registration, so students who wait
    until late registration wont be counted.
  • CS325 for the summer will cover the same material
    but have fewer projects. 2 Unix and 2 Windows.

3
Lecture 26
  • Today
  • Paint()
  • BitMaps
  • Timer

4
Projects 5 6 - 7
  • P5 WinOthello Due in Next Monday.
  • Loose assignment very basic functionality
    required two players can play Othello add
    more functionality as you wish
  • P6 WinOthelloGold Before Spring Break?
  • Ten improvements over the basic interface (not
    your basic interface over a conceptual basic
    interface P5 and P6 may be the same)
  • P7 WinFinalProject After Spring Break.
  • Show it to me during study week

5
OnPaint
  • Call OnPaint indirectly through one of these
    methods
  • Invalidate(BOOL eraseTRUE)
  • InvalidateRect(CRect paintregion, BOOL erase)
  • Calling Invalidate puts an invalidate message in
    the message queue. OnPaint will not be called
    immediately.
  • Void SomeMethod()
  • code
  • InvalidateRect(region1)
  • code
  • InvalidateRect(region2)
  • code
  • InvalidateRect(regionN)
  • This results in one (1!) call to paint and its
    at some later time. The paint regions are
    magically merged.

6
Two Major Parameter Systems
  • X1, Y1, X2, Y2
  • (Left, Top, Right, Bottom)
  • X1, Y1, W, H
  • (Left, Top, Width, Height)
  • CRect(l, t, r, b) gt x1,y1,x2,y2
  • CRect(x,y, xW,yH)
  • CRect(x,y, x100,y100)
  • CRect(CPoint CPoint)
  • CRect(CPoint(x,y) CPoint(xW,yH))
  • CRect(CPoint(x,y) CPoint(x100,y100))
  • CRect(CPoint size)
  • CRect(const CRect)
  • CRect(LPCRECT) gt CRect(CRect)

7
3 CFrameWnd Methods
  • To find the size of the window
  • GetWindowRect(CRect)
  • CRect what
  • GetWindowRect(what)
  • //after this call, what will contain the
    coordinates for the entire Window, these
    coordinates will be in relation to the edge of
    the entire screen
  • To find the size of the Client window (the white
    space)
  • GetClientRect(CRect)
  • CRect what
  • GetClientRect(what) // what is same as above
  • To resize the window
  • SetWindowPos(pointer, new-left, new-top, width,
    height, flags)
  • SetWindowPos(NULL, 10, 10, 300, 200, 0)
  • SetWindowPos(CWND, x, y, cx, cy, FLAGS)

8
Dialogs
  • Three (at least) ways to create
  • Stand alone application
  • Refer to our 1st example
  • Embedded within application as temp object
  • Declared locally to a method
  • Refer to our class examples
  • Embedded within application as attribute of the
    frame
  • MapObjects
  • Always DoModal()
  • Can return a value
  • Communicating with the dialog via DoDataExchange
  • Called automatically when either of these
    happens
  • DoModal()
  • OnOK()
  • UpdateData(bool)

9
Repainting the window
  • We have seen the need to refresh the window
    client area in several of our applications
  • Toggling between roll and tide
  • Minimizing and maximizing screen
  • How do we know will our system know when it needs
    to be redrawn?
  • Windows will notify our window when it should
    redraw itself (part of overall screen management)
  • If we want to capture this event, we have to
    override the appropriate method and specify that
    we are handling the repaint event in our message
    map.

10
Repainting our window (cont)
  • Have message sent to our window
  • We assume this will be sent when necessary
  • We can also force this even to be sent to
    ourselves by the method InvalidateRect(BOOL)
  • Overriding appropriate method
  • OnPaint () is the name of the method that needs
    to be overridden. It will have to redraw the
    screen in its current state
  • MessageMap
  • Must have the macro for this event listed in our
    CFrameWnd message map
  • ON_WM_PAINT()

11
Repaint example
  • Consider our simple program that simply printed
    out roll or tide in different colors.
  • Zip3 MenuDemo
  • demoWnd.h
  • Declaration of class derived from CFrameWnd
  • demoWnd.cpp
  • Definition of class derived from CFrameWnd
  • Message Map for class derived from CFrameWnd
  • Declaration, definition, and instantiation of
    class derived from CWinApp
  • menus.h
  • Necessary identifiers are defined
  • menus.rc
  • Description of our menu resource
  • Changes to make to this routine
  • Indicate we want to catch ON_WM_PAINT
  • Write a routine to repaint our window

12
Repainting the window
  • Changes to demoWnd.h
  • afx_msg void OnPaint()
  • Changes to message map part of demoWnd.cpp
  • BEGIN_MESSAGE_MAP
  • (CDemoWnd, CFrameWnd)
  • ON_COMMAND
  • (IDM_EXIT, OnExit)
  • ON_COMMAND
  • (IDM_TOGGLE, OnToggle)
  • ON_WM_PAINT( )
  • END_MESSAGE_MAP( )
  • The method OnPaint
  • afx_msg void
  • CDemoWndOnPaint()
  • CClientDC dc(this)
  • string strText
  • if (m_iToggle) strTextm_strTwo
  • dc.SetTextColor( RGB(0,0,255))
  • else strTextm_strOne
  • dc.SetTextColor( RGB(255,0,0))
  • dc.TextOut(50,50, strText.c_str())

13
Class Exercises
  • Add repaint capability to our menu program
  • Add the new method to the demoWnd.h file
  • Change the MESSAGE_MAP and add the OnPaint
    function to demoWnd.cpp
  • Run the program and observe the results
  • This is almost good what things do you notice
    that do not seem quite right?

14
2 problems with the current fix
  • First problem
  • What?
  • Why?
  • Second problem
  • What?
  • Why?

15
Problem One
  • The method OnPaint
  • afx_msg void
  • CMenuWndOnPaint( )
  • CClientDC dc(this)
  • string sText
  • if (m_iToggle) sTextm_sOne
  • dc.SetTextColor( RGB(255,0,0))
  • else sTextm_sTwo
  • dc.SetTextColor( RGB(0,0,255))
  • dc.TextOut(50,50, sText.c_str( ))
  • The method OnPaint went into a hard loop
  • Continuous updating of the window
  • Problem was CClientDC
  • Inside OnPaint Should be CPaintDC
  • Both are derived from CDC (Device Context Base
    Class)
  • Replace colored line with CPaintDC dc(this)

16
Why CPaintDC and not CClientDC?
  • OnPaint routine assumes that the developer
  • 1. Defines location to be repainted (indicates
    ready to paint, invoking the routine
    BeginPaint)
  • 2. Repaints what is necessary
  • 3. Indicates that painting has finished (call to
    EndPaint)
  • If we paint in OnPaint via CClientDC
  • System does not automatically do (1) (3) from
    above, not doing (3) gets us in trouble as the
    system never realizes were done with the refresh
    (since no call to EndPaint)
  • If we paint in OnPaint via CPaintDC
  • System automagically calls BeginPaint when we
    define our CPaintDC object and calls EndPaint
    when routine exits.

17
Problem Two
  • We arent refreshing screen between toggles
  • We only refresh when the WM_PAINT message is sent
    to our application.
  • How can we send this message to ourselves to
    force OnPaint to be called?
  • Invalidate(EraseTrue)
  • InvalidateRect(CRect, EraseTrue)

18
Displaying graphics
  • Can display bitmap (.bmp) files in window
  • Basic concept
  • Link a bitmap image to the program via the
    programs resource file
  • Load the bitmap image into a memory image
  • Whenever you re-paint the window, re-draw the
    image as part of the re-paint process

19
App that just displays an image
  • Header file
  • include ltafxwin.hgt
  • class CPictureWnd public CFrameWnd
  • public
  • CPictureWnd()
  • afx_msg void OnPaint()
  • private
  • CDC m_memDC
  • DECLARE_MESSAGE_MAP( )
  • Basic class declaration
  • Will put our image out on the window, and then
    repaint it whenever necessary
  • Data member
  • m_memDC contains a copy of the image in memory

20
Application (part one)
  • Constructor for the CPictureWin class
  • Create the window
  • Load in the picture into a bitmap image via
    LoadBitmap
  • This bmpPicture may be used for multiple BitMaps
  • Create compatible image in memory so that you can
    transfer the image in memory to the screen
  • Store information about the bitmap into the CDC
  • Release the current Bitmap in bmpPicture so you
    can create another one if you wish
  • CPictureWndCPictureWnd() Create(NULL, "Image
    Demo", WS_OVERLAPPEDWINDOW, CRect(100,100,500,50
    0))
  • CBitmap bmpPicture
  • bmpPicture.LoadBitmap ("MY_PICTURE")CClientDC
    dc(this)m_memDC.CreateCompatibleDC (dc)
  • m_memDC.SelectObject (bmpPicture)
  • bmpPicture.DeleteObject()

21
Application (part two)
  • afx_msg void CPictureWndOnPaint() CPaintDC
    dc(this)dc.BitBlt(50,50,120,100, m_memDC,
    0, 0, SRCCOPY)dc.BitBlt(200,200,120,100,
    m_memDC, 0, 0, SRCCOPY)
  • BEGIN_MESSAGE_MAP (CPictureWnd, CFrameWnd)
  • ON_WM_PAINT( )
  • END_MESSAGE_MAP( )
  • OnPaint routines redraws window, which includes
    the graphic image
  • Draw two copies of the image, one starting at
    (50,50) and one starting at (200,200).
  • Both draw what is in m_memDC
  • SRCCOPY is a bit-by-bit copy option

22
Application (part three)
  • class CPictureApp public CWinApp
  • public
  • BOOL InitInstance()
  • m_pMainWnd new CPictureWnd
  • m_pMainWnd-gtShowWindow (m_nCmdShow)
  • m_pMainWnd-gtUpdateWindow()
  • return TRUE
  • pictureApp
  • MY_PICT1 BITMAP "elephant.bmp"
  • Standard driver portion, loads an instance of
    CPictureWin as the application
  • Resource file shown on the left in red, only one
    line that identifies the bitmap file

23
Class Exercises
  • Download Zip4
  • Try out these 4 things
  • Modify the code so that you can get as many
    elephants as possible in the window without any
    of them overlapping
  • Involves multiple BitBlt statements in OnPaint
  • Make a hollow square of elephants.
  • Look for images on the internet to use in your
    application.
  • Add multiple images think about using a CDC
    array in order to store information about how the
    images should be displayed on the screen.
  • For multiple bitmaps, you only need multiple
    CDCs you may use one CBitmap instance to load
    the bitmaps as long as you call the
    CBitmapDeleteObject() method

24
Adding timers to our programs
  • Timers allow certain events to happen at specific
    times
  • Move things on a page
  • Provide a finite time for the user to respond
  • Simple example take our program from last time
    that displayed an elephant and move it around the
    page
  • Change our header slightly
  • Change our body (program)
  • Same resource file

25
Header Resource File
  • include ltafxwin.hgt
  • class CPictureWnd public CFrameWnd
  • public
  • CPictureWnd()
  • afx_msg void OnPaint()
  • afx_msg void OnTimer()
  • afx_msg void OnDestroy()
  • private
  • CDC m_memDC
  • int x, y
  • DECLARE_MESSAGE_MAP()
  • MY_PICTURE BITMAP "elephant.bmp"
  • Standard class header, now handle
  • Repaints
  • Timer
  • Destroy (at end of program)
  • Standard local variable
  • Resource file doesnt change

26
Program body (part 1)
  • include "pictureWnd.h"
  • CPictureWndCPictureWnd()
  • Create(NULL, "Image Example", WS_OVERLAPPEDWINDOW
    ,
  • CRect(100,100,500,500))
  • x 20 y 20
  • CBitmap bmpPicture
  • bmpPicture.LoadBitmap("MY_PICTURE")
  • CClientDC dc(this)
  • m_memDC.CreateCompatibleDC(dc)
  • m_memDC.SelectObject(bmpPicture)
  • afx_msg void CPictureWndOnDestroy()
    KillTimer(1)
  • Constructor does not change from last time, loads
    image into memory
  • New routine OnDestroy
  • invoked when window exits
  • shuts down timer (bad things happen to the OS if
    you forget this)

27
Program body (part 2)
  • afx_msg void CPictureWndOnPaint() CPaintDC
    dc(this)dc.BitBlt(x,y,120,100, m_memDC, 0,
    0, SRCCOPY)
  • afx_msg void CPictureWndOnTimer()
  • bool z FALSE
  • x10 if (x gt 200) x 20 z TRUE
  • y10 if (y gt 200) y 20 z TRUE
  • InvalidateRect(NULL, z)
  • OnPaint
  • draws image at the specified location
  • OnTimer occurs when timer event occurs
  • increments x and y
  • Forces call of OnPaint
  • Second parameter indicates whether to erase
    current window or not

28
Program body (part 3)
  • BEGIN_MESSAGE_MAP (CPictureWin,
    CFrameWnd)ON_WM_TIMER( )ON_WM_PAINT(
    )ON_WM_DESTROY( )
  • END_MESSAGE_MAP()
  • class CPictureApp public CWinApp
  • public
  • BOOL InitInstance() m_pMainWnd new
    CPictureWndm_pMainWnd-gtShowWindow(m_nCmdShow)m
    _pMainWnd-gtUpdateWindow()if (
    !m_pMainWnd-gtSetTimer(1,200,NULL) ) return
    FALSEreturn TRUE
  • pictureApp
  • Standard message map and CWinApp
  • CWinApp now also starts the timer
  • Identifier (ID)
  • Timer goes off every 200 milliseconds
  • Routine to handle timer events, NULL sends to
    current window

29
Class Exercises
  • The program is out on the web at
  • Zip6
  • pictureWnd.h
  • pictureWnd.cpp
  • resource.rc
  • elephant.bmp
  • Modify the code so that your elephant moves in a
    square (clockwise) around your window
  • Modify your code so that it
  • Moves very fast
  • Moves very slow

30
DoubleBuffering (Why isnt it automatic!)
  • afx_msg void CKalahFrameWndOnPaint()
  • //step 1 set up a buffer
  • CPaintDC paintDC(this) CDC dbufdc
  • dbufdc.CreateCompatibleDC(paintDC)
  • CRect screen GetClientRect(screen)
  • CBitmap bmp
  • bmp.CreateCompatibleBitmap(
  • paintDC, screen.Width(), screen.Height() )
  • dbufdc.SelectObject(bmp)
  • //step2 draw on dbbufdc
  • dbbuddc.TextOut()
  • dbbufdc.FillRect(CRect(x,y,xw, yh), pBrush)
  • //step3 copy buffer to screen
  • paintDC.BitBlt(0, 0, screen.Width(),
    screen.Height(),
  • dbufdc, 0, 0, SRCCOPY )

31
Another example with timers
  • Must complete a task within a specified amount of
    time
  • Could use this to have a timed game.
  • Our example program will simply count down a
    timer to zero
  • We want to see if you can do 25 mouse clicks in
    10 seconds

32
Program header
  • include ltafxwin.hgt
  • class CTimeWin public CFrameWnd
  • publicCTimeWin()afx_msg void OnLButtonDown
    (UINT, CPoint)afx_msg void OnPaint()afx_msg
    void OnTimer()afx_msg void OnDestroy()
  • privateint m_nClicksint m_nTimeLeftCFont
    m_bigFontDECLARE_MESSAGE_MAP()
  • Standard header file
  • Handle
  • Left button events
  • OnPaint events
  • OnTimer events
  • OnDestroy events
  • Class members
  • Number of clicks
  • Time left
  • A font

33
Program body (part 1)
  • include ltstrstrea.hgt
  • include "main.h"
  • CTimeWnd CTimeWnd()
  • Create(NULL, "Timer and Text Example", WS_OVERLA
    PPEDWINDOW,CRect(100,100,500,500))m_nClicks
    25m_nTimeLeft 10m_bigFont.CreateFont
  • (144,0,0,0,FW_BOLD,0,0,0,0,0,0,0,0,"Arial")Mess
    ageBox(
  • "Try to click the mouse 25 times in 10 seconds",
  • "Click Test")
  • afx_msg void CTimeWnd OnDestroy()
    KillTimer(1)
  • Standard constructor
  • Set variables
  • Define a font (size 144, bold, Arial)
  • Pop up a message box letting them know what to do
    before the window opens

34
Program body (part 2)
  • Paint routine, writes the current time left (in
    seconds) using our specified font
  • Allocate a font
  • Put text in array
  • Get size of our current window
  • Calculate middle
  • Write the info using our font, centering it on
    the screen
  • afx_msg void CTimeWnd OnPaint() CPaintDC
    dc(this)CFont pfont dc.SelectObject(m_bigFo
    nt)ostrstream ss ltlt m_nTimeLeftltlt '\0'CRect
    rectGetClientRect(rect)int midX
    (rect.right / 2) -36strlen(arText)int midY
    (rect.bottom / 2) - 72dc.SetTextColor(RGB(255,0,
    0))dc.TextOut(midX,midY, arText)

35
Program body (part 3)
  • afx_msg void CTimeWnd OnTimer() if
    (m_nTimeLeft 0) KillTimer(1)
    MessageBox("Too Slow", "Click Test")
    SendMessage(WM_CLOSE)else
    InvalidateRect(NULL) m_nTimeLeft--
  • afx_msg void CTimeWnd OnLButtonDown (UINT a,
    CPoint p) m_nClicks--if (m_nClicks0)
    KillTimer(1)MessageBox("Success", "Click
    Test")
  • Timer routine
  • If reach zero, print message and close
  • Else redraw our window and decrement the counter
  • Button routine
  • Decrement clicks left
  • If at zero, kill timer (done)

36
Program body (part 4)
  • BEGIN_MESSAGE_MAP (CTimeWnd, CFrameWnd)ON_WM_LB
    UTTONDOWN()ON_WM_TIMER()ON_WM_PAINT()ON_WM_DEST
    ROY()
  • END_MESSAGE_MAP()
  • class CTimeApp public CWinApp
  • publicBOOL InitInstance() m_pMainWnd new
    CTimeWndm_pMainWnd-gtShowWindow(m_nCmdShow)m_pM
    ainWnd-gtUpdateWindow()if ( !m_pMainWnd-gtSetTimer
    (1,1000,NULL) ) return FALSEreturn TRUE
  • timeApp
  • Standard message map
  • Standard application framework
  • Create window
  • Start timer

37
Class Exercises
  • The timer routine is out on the web
  • Zip11
  • main.h
  • main.cpp
  • Experiment 1
  • Comment out CreateFont line in the constructor
    and regenerate it watch how VC prompts you
  • Change the font size, change some other options
  • Look up CreateFont in the help for complete
    info
  • Experiment 2 Re-write this program so it tells
    how many clicks you can do in 10 secs

38
Capturing text typed in window
  • Basic idea is you want to capture keystrokes that
    are made within the window
  • Simple example
  • Capture keystrokes in the window
  • Just display the keys entered
  • Must worry about newlines and backspace keys
  • Basic assumptions for this example
  • Wont ever type more than 32 lines of 80
    characters each

39
Program Header
  • include ltafxwin.hgt
  • class CTextInputWin public CFrameWnd
  • public
  • CTextInputWin()afx_msg void OnPaint()afx_msg
    void OnChar (UINT, UINT, UINT)
  • privatechar m_arText3280int m_iRowint
    m_iLengthDECLARE_MESSAGE_MAP( )
  • Class declaration
  • OnChar routine has three arguments
  • Character
  • Repeat factor
  • Flags
  • Private data
  • Array of info typed
  • Current row
  • Current position in row

40
Program Body (part 1)
  • include "main.h"
  • CTextInputWinCTextInputWin()
  • Create(NULL, "Text Input Example",
    WS_OVERLAPPEDWINDOW,
  • CRect(100,100,500,500))
  • m_iRow 0
  • m_iLength 0
  • m_arText00 '\0'
  • afx_msg void CTextInputWinOnPaint()CPaintDC
    dc(this)for (int a0 altm_Row a)
    dc.TextOut(10, 2015a, m_arTexta)
  • Constructor
  • Build window
  • Set up local variables (first row, first column,
    null terminated)
  • OnPaint simply re-writes all the characters in
    our array, one line at a time
  • Each row is offset

41
Program Body (part 1)
  • afx_msg void CTextInputWinOnChar (UINT ch, UINT
    repeat, UINT flags)
  • switch (ch) case '\r' m_arTextm_Rowm_Le
    ngth '\0' m_Row m_arTextm_Row0
    '\0' m_Length 0 breakcase '\b'
    if (m_Length gt 0) m_Length--
    breakdefault m_arTextm_Rowm_Lengthch
    m_arTextm_Rowm_Length
    '\0'InvalidateRect(NULL,)
  • Process a char
  • Switch on type of character
  • Newline, move to next row in array
  • Backspace, reset length of line
  • Normal char, add it to the line and mark the next
    position as the end
  • Repaint window

42
Program Body (part 3)
  • BEGIN_MESSAGE_MAP (CTextInputWin,
    CFrameWnd)ON_WM_PAINT( )ON_WM_CHAR( )
  • END_MESSAGE_MAP( )
  • class CTextInputApp public CWinApp
  • public
  • BOOL InitInstance() m_pMainWnd new
    CTextInputWinm_pMainWnd-gt ShowWindow(m_nCmdShow
    )m_pMainWnd-gtUpdateWindow()return TRUE
  • textApp
  • Message map handles character events and window
    repaints
  • Standard driver

43
Class Exercises
  • Download the example from class
  • Zip8
  • Run the program.
  • Does a line of 79 characters or more wrap?
  • Does backspace erase characters or just logically
    remove them?
  • Can you backspace up multiple lines?
  • How would you fix your program to backspace up
    multiple lines?
  • What happens if you type more than 32 lines or if
    you backspace when there is nothing there

44
Dialog Boxes
  • Can include both check boxes and radio
    buttons in a dialog box
  • Check boxes have two states
  • Checked
  • Not checked
  • Radio buttons have a number of alternatives
  • Only one alternative may be selected

45
Adding check boxes
  • Processing the button
  • CButton pButton1 (CButton )
    GetDlgItem(IDC_ID1)
  • CButton pButton2 (CButton )
    GetDlgItem(IDC_ID2)
  • if ( pButton1-gtGetCheck( ) )
  • MessageBox(ID1 Checked", "old")
  • else
  • MessageBox(ID1 Not Checked", "old")
  • if ( pButton2-gtGetCheck( ) )
  • Add to rc file
  • MyDialog DIALOG 20,20,100,100
  • CAPTION Some Caption
  • LTEXT
  • EDITTEXT
  • DEFPUSHBUTTON
  • AUTOCHECKBOX "New,
  • IDC_ID1, 65, 10, 30, 20
  • AUTOCHECKBOX "Old, IDC_ID2, 65, 40, 30, 20
  • Add identifiers to identifiers.h file

46
Adding Radio Buttons
  • Resource File
  • GROUPBOX "A B C" , IDM_RADIO,100,100,60,60
  • AUTORADIOBUTTON "A", IDM_A, 120, 120, 10, 10
  • AUTORADIOBUTTON "B", IDM_B, 130, 130, 10, 10
  • AUTORADIOBUTTON "C", IDM_C, 140, 140, 10, 10
  • Groupbox (above) outlines the set of radio
    buttons
  • Code (other side) retrieves the checked option
    (within range of IDM_A to IDM_C)
  • Code in your routines
  • int ans GetCheckedRadioButton (IDM_A, IDM_C)
  • switch (ans)
  • case IDM_A MessageBox ("selected option A",
    "select") break
  • case IDM_B MessageBox ("selected option B",
    "select") break
  • case IDM_C MessageBox ("selected option C",
    "select") break

47
Class Exercises
  • Zip 9
  • Add two more option buttons (options 3 4)
  • Move the OK button down to the bottom of the
    dialog box, and make it square
  • Add two more radio buttons, line all up
    vertically
  • Make sure you can separate functionality and what
    methods perform what events.
  • Check out and play around with
  • SetWindowPos(NULL, 10, 10, 300, 200, 0)
Write a Comment
User Comments (0)
About PowerShow.com