Why would a dialog erase its content without refreshing? - windows

I'm having this very strange problem where a window seems to be erasing its content and not redrawing it after erasing it. This dialog is derived from CDHtmlDialog, which I think is part of the problem. There is some sort of non-deterministic code execution happening resulting in some code being executed prior to others in certain cases and the opposite in others.
Message handlers that are involved are:
BEGIN_MESSAGE_MAP(CCalcDrillDownDlg, CDHtmlDialog)
ON_WM_PAINT()
END_MESSAGE_MAP()
BEGIN_EVENTSINK_MAP(CCalcDrillDownDlg, CDHtmlDialog)
ON_EVENT(CCalcDrillDownDlg, AFX_IDC_BROWSER, 250 /* BeforeNavigate2 */, _OnBeforeNavigate2b, VTS_DISPATCH VTS_PVARIANT VTS_PVARIANT VTS_PVARIANT VTS_PVARIANT VTS_PVARIANT VTS_PBOOL)
END_EVENTSINK_MAP()
The OnInitDialog() function is as follows:
BOOL CCalcDrillDownDlg::OnInitDialog()
{
SetHostFlags(DOCHOSTUIFLAG_FLAT_SCROLLBAR);
CDHtmlDialog::OnInitDialog(); // << will eventually call _OnBeforeNavigate2b()
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
LoadFromResource(IDR_CALC_DRILLDOWN); // << will eventually call _OnBeforeNavigate2b()
CString title = getStr2Ptr(22574);
SetWindowText(title);
ShowWindow(SW_SHOW);
return TRUE; // return TRUE unless you set the focus to a control
}
This is the OnPaint() function:
void CCalcDrillDownDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
// Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDHtmlDialog::OnPaint();
}
}
I've not put the contents of the _OnBeforeNavigate2b() function as it appears not to have anything to do with the redrawing system.
So what appears to happen is that sometimes, the dialog contents will be painted somehow prior to calling CCalcDrillDownDlg::OnPaint(). If this happens, then the call to CDHtmlDialog::OnPaint() will wipe the contents off the window.
Other times, the contents are not painted on the window prior to calling CCalcDrillDownDlg::OnPaint(). If this happens, then the call to CDHtmlDialog::OnPaint() will probably still wipe the contents off the window, which hasn't been painted yet, and then sometime after the call to CCalcDrillDownDlg::OnPaint(), it gets redrawn.
Spy++ doesn't capture any messages when the system properly redraws the window, so I've removed the messages generated from this question.
Does anyone have any idea as to how the redrawing is getting done and why the order gets foobarred sometimes?
Edit
Here is the contents of the IDR_CALC_DRILLDOWN resource:
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Calculation Drilldown</title>
<style type="text/css">
body { overflow-y: auto; font-family: arial, Helvetica, sans-serif; font-size: 90%; }
a:link { color: black; }
a:visited { color: black; }
table { border-collapse: collapse; }
tr.runcache td { background-color: #B5B5B5; color: black; }
tr.runcache td a:link { color: black; }
tr.runcache td a:visited { color: black; }
tr.tracker td { background-color: white; color: black; }
tr.tracker td a:link { color: black; }
tr.tracker td a:visited { color: black; }
td.numericvalue { text-align: right; }
tr.paramTitle td { background-color: #4A4A4A; color: white; }
tr.resultTitle td { background-color: #4A4A4A; color: white; }
tr.resultTitle td a:link { color: white; }
tr.resultTitle td a:visited { color: white; }
tr.param td { background-color: white; color: black; }
tr.param td a:link { color: black; }
tr.param td a:visited { color: black; }
span.selection { background-color: #EBEBEB; }
</style>
</head>
<body>
<div id="calculation"></div>
<div id="details" style="padding-left: 0.1in; display: none;"></div>
</body>
</html>
Edit #2
Further investigation seems to show that the CDHtmlDialog class (or a base class thereof) will draw the window, irrespective of if my CCalcDrillDownDlg::OnPaint() calls CDHtmlDialog::OnPaint() or not, which is just weird and not intuitive. :(
Also, it seems that this is possibly threading related, as this seems to be dependant on how long it takes to render the window. If it takes a short time, it displays fine. If it takes a half a second or more, it screws up.
For the moment, I'm using a workaround where I have a m_bRepaint flag in the class which is initially set to true. Upon calling CCalcDrillDownDlg::OnPaint() and it is not iconic, I check the flag and force a resize. This is not optimal as it causes an initial flicker, but it at least it makes sure that the window's contents are drawn.
if (!m_bRepaint)
{
CDHtmlDialog::OnPaint();
}
else
{
CRect winRect;
GetWindowRect(&winRect);
SetWindowPos(NULL, 0, 0, winRect.Width() - 1, winRect.Height(), SWP_NOMOVE | SWP_NOZORDER);
SetWindowPos(NULL, 0, 0, winRect.Width() , winRect.Height(), SWP_NOMOVE | SWP_NOZORDER);
m_bRepaint = false;
}
Using Invalidate() does not work. I have to resize it to something other than it's current size and resize it back.
This CDHtmlDialog class is a PITA to work with and I wouldn't recommend anybody use it if they have a choice.

Ok, so it would seem that this is caused by the windows message queue not being deterministic, so it would seem that the underlying COM control is painting on it's DC prior to the WM_PAINT message.
To workaround the issue, I wait for the window to show itself by waiting for WM_WINDOWPOSCHANGED message, posting another application message which will then call Invalidate() and UpdateWindow(), thus forcing the redrawing of the window.
This technique is described here on Raymond Chen's blog "The Old New Thing".

Don't handle WM_ERASEBKGND.Set WM_CLIPCHILDREN style on the dialog.
ON_WM_ERASEBKGND()
...
BOOL CCalcDrillDownDlg::OnEraseBkgnd(CDC* pDC)
{
// TODO: Add your message handler code here and/or call default
return TRUE;
}

Related

Represent a three.js GUI button with an icon

I want to communicate a "Go Left" button, in a three.js application, by using a left-arrow icon (instead of just labelling it "left")
Many of the three.js examples use dat.GUI to set up GUI control (e.g. button, slider). In all these examples the buttons show up as rectangular boxes
Is it possible to represent a dat.GUI button with an icon? (or at least place a background image behind the button?)
Otherwise, are there other GUI alternatives that are easy to use with three.js?
EDIT:
I'm having trouble to embed the css code inside javascript.
I added the code below and when I click on the button it displays in the console "BEG setStyle", i.e. the function setStyle() is executed.
But I don't see a change in the color or the background image of the "Nukeem all!" button.
#prisoner849 Can you help me with this?
Thanks
var gui = new dat.GUI(),
var obj = {
add:function()
{
console.log("clicked")
updateTheta();
this.setStyle();
},
setStyle:function()
{
console.log("BEG setStyle")
this.color = "#00ff00";
this.backgroundImage = "url('https://cdn4.iconfinder.com/data/icons/6x16-free-application-icons/16/Radiation.png')";
}
};
gui.add(obj, 'add').name('Nukeem all!');
Thanks.
TheJim01 is right. You can do the trick with CSS.
Here is just a rough concept:
var gui = new dat.GUI();
var obj = {
add: function() {
alert("clicked!")
}
};
gui.add(obj, "add").name("Nuke'em all!");
gui.add(obj, "add").name("I'm Fine!");
gui.add(obj, "add").name("Harmony");
var fourth = gui.add(obj, "add").name("CSS is awesome!");
var fourthStyle = fourth.domElement.previousSibling.style;
fourthStyle.backgroundImage = 'url(https://cdn1.iconfinder.com/data/icons/hawcons/32/700035-icon-77-document-file-css-16.png)';
fourthStyle.backgroundRepeat = 'no-repeat';
fourthStyle.backgroundPosition = 'left';
fourthStyle.backgroundColor = 'white';
fourthStyle.color = 'black';
console.log(fourthStyle);
.function:nth-child(1) .property-name {
background-image: url('https://cdn4.iconfinder.com/data/icons/6x16-free-application-icons/16/Radiation.png');
background-repeat: no-repeat;
background-position: right;
background-color: gray;
color: yellow;
}
.function:nth-child(2) .property-name {
background-image: url('https://cdn4.iconfinder.com/data/icons/6x16-free-application-icons/16/OK.png');
background-repeat: no-repeat;
background-position: center;
background-color: teal;
color: aqua;
}
.function:nth-child(3) .property-name {
background-image: url('https://cdn4.iconfinder.com/data/icons/6x16-free-application-icons/16/In-yang.png');
background-repeat: no-repeat;
background-position: left;
background-color: pink;
color: red;
text-align: right;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.7.1/dat.gui.min.js"></script>

Updating variables created by lighten/darken functions by modifying the original base color afterwards

I'm currently trying to create a mix-in that will let me build buttons with hover values using the darken and lighten color functions in sass. My code for some reason is spitting out white and black for the background color instead of the hex value of a returned color. Here it is on code pen: http://codepen.io/malikabee/pen/vEQZOv
$btn_color: #fff;
$btn_alpha: 1;
$btn_color_amount: 100%;
$color_funcs: (
'darken': darken($btn_color, $btn_color_amount),
'lighten': lighten($btn_color, $btn_color_amount),
'transparentize': transparentize($btn_color, $btn_alpha)
);
#mixin _btn_color($base_color, $amount, $hover){
background: $base_color;
a:hover,
a:focus{
#each $func_name, $color_func in $color_funcs{
#if($func_name == $hover){
$btn_color: $base_color;
$btn_color_amount: $amount;
background-color: $color_func;
}
}
}
}
.btn{
display: inline-block;
vertical-align: bottom;
text-align: center;
border-radius: 10px;
text-decoration: none;
}
.btn_blue{
#include _btn_color(#3c3c3c, 10%, 'darken');
}
Once you get past this block of code, the expressions don't exist anymore, only the value they evaluated to does:
$color_funcs: (
'darken': darken($btn_color, $btn_color_amount),
'lighten': lighten($btn_color, $btn_color_amount),
'transparentize': transparentize($btn_color, $btn_alpha)
);
Changing $btn_color after this point does nothing. Sass cannot to go back in time and re-run those expressions because they've already been evaluated using the original color (black).
What you can do instead is use the call function.
#mixin _btn_color($base_color, $amount, $func){
background: $base_color;
a:hover,
a:focus{
background-color: call($func, $base_color, $amount);
}
}
.btn_blue{
#include _btn_color(blue, 10%, 'darken');
color: white;
}

nvd3 angularjs fixed tooltip

I'm trying to fix the graph but the tooltip is not fixed and have strange behavior where the tooltip start to float around the window.
I have tried to put in the nvd3.css the position fixed but didn't work:
.nvtooltip {
**position: fixed;**
background-color: rgba(255,255,255,1.0);
padding: 1px;
border: 1px solid rgba(0,0,0,.2);
z-index: 10000;
font-family: Arial;
font-size: 13px;
text-align: left;
pointer-events: none;
white-space: nowrap;
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
Any advice?
Try to use fixedTop option of nv.models.tooltip model. This is inside the interactiveLayer chart option. So, you can set this up like:
nv.addGraph(function() {
var chart = nv.models.lineChart()
.useInteractiveGuideline(true) //required
...
//shoud be separated
chart.interactiveLayer.tooltip.fixedTop(100) //fixed distance from top
...
})
Here is a demo
Additional tooltip options (from the source):
content = null //HTML contents of the tooltip. If null, the content is generated via the data variable.
data = null // Tooltip data. If data is given in the proper format, a consistent tooltip is generated.
gravity = 'w' //Can be 'n','s','e','w'. Determines how tooltip is positioned.
distance = 50 //Distance to offset tooltip from the mouse location.
snapDistance = 25 //Tolerance allowed before tooltip is moved from its current position (creates 'snapping' effect)
fixedTop = null //If not null, this fixes the top position of the tooltip.
classes = null //Attaches additional CSS classes to the tooltip DIV that is created.
chartContainer = null //Parent DIV, of the SVG Container that holds the chart.
tooltipElem = null //actual DOM element representing the tooltip.
position = {left: null, top: null} //Relative position of the tooltip inside chartContainer.
enabled = true //True -> tooltips are rendered. False -> don't render tooltips.

Mouse hover applied to jQPLOT X AXIS TICKS

I am trying to add mouse hover function to my axis ticks.
what i want is to show long ticks full text only on hover else it would be showing only few characters . i am adding a hover event to .jqplot-xaxis-tick .But it doesnot even respond to hover.Please suggest !
.jqplot-xaxis-tick {
top: 0px;
/* initial position untill tick is drawn in proper place */
left: 15px;
/* padding-top: 10px;*/
vertical-align: top;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.jqplot-xaxis-tick :hover{
overflow:visible;
white-space: normal;
width: auto;
position: absolute;
background-color:yellow;
}
The hover is not detecting because of the z-index of the canvas which lies on top of the whole chart. I did the following and now it's shorten the tootip by CSS ellipsis and show the tooltip with full name on hover.
Based on the Gyandeep's answer, the exact JS and CSS I used are,
Javascript:
$('div.jqplot-xaxis-tick').each(function (i, obj) {
$(this).prop('title', ($(this).text()));
$(this).css('z-index', 999); // this is important otherwise mouseover won't trigger.
});
CSS:
.jqplot-xaxis .jqplot-xaxis-tick {
position: absolute;
white-space: pre;
max-width: 92px; // Change it according to your need
overflow: hidden;
text-overflow: ellipsis;
}
The JavaScript part needs to be executed after every rendering of chart. It's better to put them right after plotting the chart and may in the AJAX success handler.
I managed to add a tooltip kindof feature to axis ticks.When I hover upon them it shows a separate box with full text else only 3-4 characters are shown.
The code is something like this
$($('.jqplot-xaxis-tick')[i]).bind('mouseover', function () {
// var m= '-webkit-marquee';
$($('.jqplot-xaxis-tick')[i]).css('white-space','pre-line');
$($('.jqplot-xaxis-tick')[i]).css('overflow','visible');
$($('.jqplot-xaxis-tick')[i]).css('width','auto');
$($('.jqplot-xaxis-tick')[i]).css('position','absolute');
$($('.jqplot-xaxis-tick')[i]).css('background-color','#666666');
$($('.jqplot-xaxis-tick')[i]).css('color','white');
$($('.jqplot-xaxis-tick')[i]).css('top','-45px');
// $($('.jqplot-xaxis-tick')[i]).css('overflow-x',m);
// console.log($($('.jqplot-xaxis-tick')[i]).text());
}).bind('mouseout', function () {
//var m= '';
//$($('.jqplot-xaxis-tick')[i]).css('overflow-x',m);
$($('.jqplot-xaxis-tick')[i]).css('white-space','nowrap');
$($('.jqplot-xaxis-tick')[i]).css('overflow','hidden');
$($('.jqplot-xaxis-tick')[i]).css('width','50');
$($('.jqplot-xaxis-tick')[i]).css('background-color','');
$($('.jqplot-xaxis-tick')[i]).css('color','grey');
$($('.jqplot-xaxis-tick')[i]).css('top','0px');
});
Here's the solution I'm using to display monthly high and low temperatures. Hovering over the x-axis tick will display an alert with the active month name and temps.
// Set up hover function
$('#monthlyTemps .jqplot-xaxis-tick').hover(function () {
setActiveColumn($(this));
});
// Set active column
function setActiveColumn(sender) {
// Display values
var monthName = sender.text();
var monthIndex = monthNames.indexOf(monthName);
var monthLowTemp = getMonthLowTemp(monthIndex);
var monthHighTemp = getMonthlHighTemp(monthIndex);
alert(monthName + ': ' + monthLowTemp + ' / ' + monthHighTemp);
}
// Get month low temp
function getMonthLowTemp(monthIndex) {
var value= $("#monthlyTemps .jqplot-point-label.jqplot-series-0.jqplot-point-" + monthIndex).text();
return value;
}
// Get month high temp
function getMonthlyHighTemp(monthIndex) {
var value= $("#monthlyTemps .jqplot-point-label.jqplot-series-1.jqplot-point-" + monthIndex).text();
return value;
}
var monthNames = new Array(12);
monthAbbreviations[0] = "Jan";
monthAbbreviations[1] = "Feb";
monthAbbreviations[2] = "Mar";
monthAbbreviations[3] = "Apr";
monthAbbreviations[4] = "May";
monthAbbreviations[5] = "Jun";
monthAbbreviations[6] = "Jul";
monthAbbreviations[7] = "Aug";
monthAbbreviations[8] = "Sep";
monthAbbreviations[9] = "Oct";
monthAbbreviations[10] = "Nov";
monthAbbreviations[11] = "Dec";

CSS3 Animation Question

How can I make a CSS3 Animation play to the end and then stop dead. I don't want it to return the elements being transformed back to their initial states.
Right now I'm using some javascript to add a class to the element after the animation's duration with the same properties as 100% in the animation.
This is possible with the "animation-fill-mode" defined as "forwards", at least in Webkit. I got this result with code like this:
#-webkit-keyframes test {
100% { background-color: #0000ff; }
}
a { background-color: #ff0000; }
a:hover { -webkit-animation: test 1s 1 ease forwards }
Note that specifying start color in 0% keyframe and end color in :hover was not necessary.
Of course, this code is Webkit specific. I haven't tried in other browsers with other vendor prefixes or with the general "animation" property.
put your end values in the main css class and the start values in the animation keyframes at 0%:
#keyframes test {
0% {
background-color: #ff0000; /* start value */
}
100% {
background-color: #0000ff;
}
}
a {
background-color: #ff0000; /* normal state */
}
a:hover {
animation-name: test;
animation-duration: 1s;
background-color: #ff0000; /* final state, after animation is finished */
}
In case this question is still open, I don't think this is possible using CSS3 animations as they're currently specified:
An animation does not affect the computed value before the application of the animation, before the animation delay has expired, and after the end of the animation.
However, you should be able to use CSS3 transitions for basic effects. There's a slide in the html5rocks.com presentation that shows how to do this. Here's the relevant [paraphrased] excerpt:
#box.left { margin-left: 0; }
#box.right { margin-left: 1000px; }
#box { -webkit-transition: margin-left 1s ease-in-out; }
// Run this to animate to the left
document.getElementById('box').className = 'left';
// Run this to animate to the right
document.getElementById('box').className = 'right';
animation-fill-mode: forwards
The animation-fill-mode CSS property specifies how a CSS animation should apply styles to its target before and after it is executing

Resources