C#WinForms,具有半透明背景的工具提示

时间:2018-07-26 12:30:12

标签: c# .net winforms

我正在研究这个小型WinForm应用程序,因此决定使用具有半透明背景的自定义绘制工具提示。因此,我首先将ToolTip上的 public void setupData(){ String image = movie.getMoviePoster(); String title = movie.getTitle(); String releaseDate = movie.getDate(); String voteAverage = movie.getVoteAverage(); String plot = movie.getPlot(); ImageView poster = findViewById(R.id.details_image); Picasso.with(this).load(image).into(poster); TextView name = findViewById(R.id.details_title); name.setText((getResources().getString(R.string.movie_title)) + " " + title); TextView dateRelease = findViewById(R.id.details_release_date); dateRelease.setText((getResources().getString(R.string.release_date)) + " " + releaseDate); TextView averageVote = findViewById(R.id.details_voter_average); averageVote.setText((getResources().getString(R.string.vote_average)) + " " + voteAverage); TextView moviePlot = findViewById(R.id.details_plot); moviePlot.setText((getResources().getString(R.string.plot)) + " " + plot); } 属性设置为OwnerDraw,为TrueDraw事件创建了事件处理程序(请参见下面的示例代码。工作)。

Popup

现在,当第一次为特定控件显示工具提示时,一切都会按预期进行。请参见下面的图片(带有半透明红色背景的400x400工具提示)。

enter image description here

但是当我第二次将鼠标悬停在同一控件上时,ToolTip失去了半透明性。参见下面的图片。为什么会这样?

enter image description here

3 个答案:

答案 0 :(得分:1)

谢谢大家的帮助。我非常确定Ben Voigts的答案或Jimis的评论也可以通过某种方式解决此问题(我将稍后尝试它们,如果可以使用,请更新答案)。

我的解决方案基于Hans Passant的第一条评论,他建议在Graphics.CopyFromScreen()事件处理程序(Popup)中使用toolTipDay_Popup,以捕获工具提示下的图像,然后在Draw事件处理程序(toolTipDay_Draw)中,我只是绘制了捕获的图像。

(Hans Passant指出了DPI缩放比例不同的问题,但是可以通过How to get Windows Display settings?中的Farshid T答案+来解决,但我没有在下面的代码中包含它)。

所以我现在使用的解决方案如下:

Bitmap dayToolTipBackground = new Bitmap(200, 200);
private void toolTipDay_Popup(object sender, PopupEventArgs e)
{
     e.ToolTipSize = new Size(200, 200);
     var backGraphics = Graphics.FromImage(dayToolTipBackground);
     var cursorPosition = Cursor.Position;
     backGraphics.CopyFromScreen(new Point(Cursor.Position.X, Cursor.Position.Y + 21), new Point(0, 0), new Size((200, 200)));    
}


private void toolTipDay_Draw(object sender, DrawToolTipEventArgs e)
{
     e.Graphics.DrawImage(dayToolTipBackground, new Point(0, 0));
     e.Graphics.FillRectangle(new SolidBrush(Color.FromArgb(120, Color.Red)), new Rectangle(e.Bounds.Location, e.Bounds.Size));
}

答案 1 :(得分:0)

第一次将鼠标悬停在控件上时,将创建带有透明颜色(ARGB.120)的新的工具提示实例。当您在工具提示外部单击时,工具提示对象是否已被完全释放,还是只是将实例设置为不可见?

当第二次将鼠标悬停在实例上时,如果旧的工具提示对象没有被处置,则有可能再次调用同一对象。因此,现在当您在现有的工具提示上使用color = ARGB.120进行Graphics.FillRectangle()时,您只是在其上覆盖了另一层ARGB.120颜色,这将使它进一步变暗,因为颜色级别已更改。

因此,第一次调用工具提示后,如果您在工具提示之外单击,则可能需要处理工具提示对象(或e.Graphics对象,如果不影响应用程序的其他部分)并创建新的每次将鼠标悬停在控件上时,都会出现工具提示对象。

答案 2 :(得分:-1)

需要告知Windows弹出窗口下方的窗口需要重绘。这是通过“分层窗口”样式完成的。通过分层,可以按z顺序绘制内容,并且可以进行透明度混合。如果不分层,则仅向顶部窗口发送重绘,并在DC的屏幕缓冲区中毫无意义的剩余数据之上进行绘制。

您可以尝试p/invoking SetLayeredWindowAttributes

我强烈建议阅读分层Windows上的MSDN文档:  Herehere