Przemek
>Yes, it is.
I suspected so.
<<<<<
It's enough to overload PUTCHAR() method and call TOUCHCELL() inside,
f.e. add to gtwvg.c:
static BOOL hb_gt_wvg_PutChar( PHB_GT pGT, int iRow, int iCol,
BYTE bColor, BYTE bAttr, USHORT usChar )
{
if( HB_GTSUPER_PUTCHAR( pGT, iRow, iCol, bColor, bAttr, usChar ) )
{
HB_GTSELF_TOUCHCELL( pGT, iRow, iCol );
return TRUE;
}
return FALSE;
}
and to hb_gt_FuncInit() function:
pFuncTable->PutChar = hb_gt_wvt_PutChar;
It will cause that "touched" screen characters will be always redrawn.
>>>>>>>
Yes it is ok with above change, so I need to include this in GTWVG.
<<<<<
This is sth what we should probably discuss in the future. It's not clear
for me how GTWVG uses different display context and merge it to show final
screen, what is the priority of text and GUI objects, how it interacts with
SAVE/REST screen. Of course I can see what happens in current code but I'd
like to know the ideas rather then results of implementation because it is
hardly oriented to MS-Windows API.
>>>>>
The priority:
a) Text
b) GUI elements based on the coordinates of the region retrieved by
GetUpdateRect() in WM_PAINT window message. GUI elements are stored in an
array as per this structure:
1) cObjectID . Character ID to handle in-place change/retrieve particular
paint object
2) nIDinObject . Numeric ID to change a particular paint block in
<cObjectID>
3) bPaintFunc . Block to a paint function in wvtcore.c
4) aCoOrdinates . Optional. An array of screen coordinates where that
object belongs to { nTop, nLeft, nBottom, nRight } in row/columns.
This is a sample of such placement:
SetPaint( 'MSGBOX', 1009, ;
{|| Wvt_DrawLabel( 10, 10, 'Vouch', nAlign, nil, nRGBText,
nRGBBack, ;
cFontName, 18, 0, 700, nil, .f. ) }, {
9,9,11,30 } )
And this functions set is employed to store/restore/paint the GUI elements
in WvtPaint.prg
//-------------------------------------------------------------------//
static paint_:= { { '', {} } }
//-------------------------------------------------------------------//
//
// This function must have to be defined in your appls
/*
function Wvt_Paint()
WvtPaintObjects()
return nil
*/
//-------------------------------------------------------------------//
function WvtPaintObjects()
LOCAL i, lExe, nLeft, nRight, b, tlbr_, aBlocks, nBlocks
aBlocks := WvtSetPaint()
if ( nBlocks := len( aBlocks ) ) > 0
tlbr_:= Wvt_GetPaintRect()
for i := 1 to nBlocks
lExe := .t.
if aBlocks[ i,3 ] <> nil .and. !empty( aBlocks[ i,3 ] )
// Check parameters against tlbr_ depending upon the
// type of object and attributes contained in aAttr
//
do case
case aBlocks[ i,3,1 ] == WVT_BLOCK_GRID_V
b := aBlocks[ i,3,6 ]
if len( b:aColumnsSep ) == 0
lExe := .f.
else
nLeft := b:aColumnsSep[ 1 ]
nRight := b:aColumnsSep[ len( b:aColumnsSep ) ]
if !( tlbr_[ 1 ] <= aBlocks[ i,3,4 ] .and. ; // top <
bottom
tlbr_[ 3 ] >= aBlocks[ i,3,2 ] .and. ; // bootm >
top
tlbr_[ 2 ] <= nRight + 1 .and. ; // left <
right
tlbr_[ 4 ] >= nLeft - 2 ) // right >
left
lExe := .f.
endif
endif
case aBlocks[ i,3,1 ] == WVT_BLOCK_GETS
if !( tlbr_[ 1 ] <= aBlocks[ i,3,4 ] .and. ; // top < bott
tlbr_[ 3 ] >= aBlocks[ i,3,2 ] .and. ; // bootm > top
tlbr_[ 2 ] <= aBlocks[ i,3,5 ] .and. ; // left < righ
tlbr_[ 4 ] >= aBlocks[ i,3,3 ] ) // right > left
lExe := .f.
endif
otherwise
// If refreshing rectangle's top is less than objects' bottom
// and left is less than objects' right
//
if !( tlbr_[ 1 ] <= aBlocks[ i,3,4 ] .and. ; // top <=
bottom
tlbr_[ 3 ] >= aBlocks[ i,3,2 ] .and. ; // bootm >= top
tlbr_[ 2 ] <= aBlocks[ i,3,5 ] .and. ; // left < right
tlbr_[ 4 ] >= aBlocks[ i,3,3 ] ) // right > left
lExe := .f.
endif
endcase
endif
if lExe
eval( aBlocks[ i,2 ] )
endif
next
endif
return ( 0 )
//-------------------------------------------------------------------//
function WvtSetPaint( a_ )
local o
static s := {}
o := s
if a_ <> nil
s := a_
endif
return o
//-------------------------------------------------------------------//
function SetPaint( cID, nAction, xData, aAttr )
local n, n1, oldData
if xData <> nil
if ( n := ascan( paint_, { |e_| e_[ 1 ] == cID } ) ) > 0
if ( n1 := ascan( paint_[ n,2 ], {|e_| e_[ 1 ] == nAction } ) ) > 0
oldData := paint_[ n,2,n1,2 ]
paint_[ n,2,n1,2 ] := xData
paint_[ n,2,n1,3 ] := aAttr
else
aadd( paint_[ n,2 ], { nAction,xData,aAttr } )
endif
else
aadd( paint_, { cID, {} } )
n := len( paint_ )
aadd( paint_[ n,2 ], { nAction, xData, aAttr } )
endif
endif
return oldData
//-------------------------------------------------------------------//
function GetPaint( cID )
local n
if ( n := ascan( paint_, { |e_| e_[ 1 ] == cID } ) ) > 0
return paint_[ n,2 ]
endif
return {}
//-------------------------------------------------------------------//
function DelPaint( cID, nAction )
local xData, n1, n
if ( n := ascan( paint_, { |e_| e_[ 1 ] == cID } ) ) > 0
if ( n1 := ascan( paint_[ n,2 ], {|e_| e_[ 1 ] == nAction } ) ) > 0
xData := paint_[ n,2,n1,2 ]
paint_[ n,2,n1,2 ] := {|| .t. }
endif
endif
return xData
//-------------------------------------------------------------------//
function PurgePaint( cID,lDummy )
local n, aPaint
DEFAULT lDummy TO .f.
if ( n := ascan( paint_, { |e_| e_[ 1 ] == cID } ) ) > 0
aPaint := paint_[ n ]
ADel( paint_, n )
aSize( paint_, len( paint_ ) - 1 )
endif
if lDummy
WvtSetPaint( {} )
endif
return ( aPaint )
//-------------------------------------------------------------------//
function InsertPaint( cID, aPaint, lSet )
local n
DEFAULT lSet TO .f.
if ( n := ascan( paint_, { |e_| e_[ 1 ] == cID } ) ) > 0
paint_[ n ] := aPaint
else
aadd( paint_, aPaint )
endif
if lSet
WvtSetPaint( aPaint )
endif
return nil
//-------------------------------------------------------------------//
When GT window receives WM_PAINT message through WndProc, after drawing the
text region, prg defined function WVT_PAINT() is fired which calls
WvtPaintObjects(). In WvtPaintObject() it is checked if any paint object
array exists. If yes, then if 4th parameter <aCoordinates> is defined then
it is checked for if the reqion being painted falls within its preview, if
yes, the paint block is executed. In case <aCoordinates> is undefined, the
paint block is executed irrespective of screen reqion under request.
For SAVE/REST another function is employed,
Wvt_SaveScreen()/Wvt_RestScreen(). Wvt_SaveScreen() creates a memory bitmap
of the requested region and returns its handle to the application which is
passed to Wvt_RestScreen() with a flag as if this need be destroyed.
For events beyond application control. mainly, KILLFOCUS; MINIMIZE;
OVERLAPPING by another Window; etc; are handled differently than SAVE/REST
mechanism, and this is transparent to the user, I mean automatic. GTWVG
writes to a compatible DC every screen command, text and gui. At any time
window receives WM_SETFOCUS/WM_KILLFOCUS message, it sets a flag to this
effect. When WM_PAINT callback is entertained, the next action is based on
this flag. If previously window had lost foct, which is not an appln
behavior, it transfers the screen region from compatible DC to window DC.
I wished to SAVE/REST functionality to be GT dependent, but because I was
not having any knowledge of core GT layer, I ended up with above solution.
Theoretically this can be accomplished with core functions SaveScreen() and
RestScreen(). Just we need to design a mechanism to save bitmap info tie
with DispCount() as there could be n number of Save/Restores.
Hope this will be useful in understanding GUI behavior.
Regards
Pritpal Bedi, INDIA-USA
--
View this message in context:
http://www.nabble.com/Screen-Painting---SetColor%28-%27N-W%27-%29---Bug-tp14232149p14299299.html
Sent from the Harbour - Dev mailing list archive at Nabble.com.
_______________________________________________
Harbour mailing list
[email protected]
http://lists.harbour-project.org/mailman/listinfo/harbour