C++实现UMG中自定义不规则形状按钮
2017-01-14 16:50
543 查看
因为要在项目中使用UMG功能,所以找到项目中名称为 "项目名称.Build.cs" 文件,加入如下代码
创建一个Button的子类
生成的初始代码:
在上面代码的基础上修改后的代码:
把上面的代码复制到你的项目中, 根据自己的实际项目名称和类名称进行修改。编译成功后打开UE4创建UMG, 这时就会在UMG的Palette面板 Common分类中看到通过C++定义的按钮。把按钮拖拽到Canvas上,在Details面板中的AdvancedHitTest分类下边的Advanced Hit Texture 设置为你按钮想显示的图片。图片的主显示内容以外的区域必须是全透明的,否则无效。 Appearenace->Style:
Normal, Hovered, Pressed 都设置为相同的图片,并且DrawAs属性设置为Image
运行,最终效果如下,鼠标只有在图形上边点击才会响应点击事件
创建一个Button的子类
生成的初始代码:
//CustomButton.h // Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "Components/Button.h" #include "CustomButton.generated.h" /** * */ UCLASS() class LEARNUE4CPP_API UCustomButton : public UButton { GENERATED_BODY() };
// CustomButton.cpp // Fill out your copyright notice in the Description page of Project Settings. #include "LearnUE4Cpp.h" #include "CustomButton.h"
在上面代码的基础上修改后的代码:
//CustomButton.h // Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "Engine.h" #include "Runtime/UMG/Public/UMG.h" #include "Runtime/UMG/Public/UMGStyle.h" #include "Components/Button.h" #include "CustomButton.generated.h" /** * Classic Slate Button with Advanced Hit implementation. * Use SetAdvancedHitTexture to set unique button's geometry, determined by it's alpha channel. * Use SetAdvancedHitAlpha to set an integer in range 0-255. If pixel's alpha is lower than this value, it will be treated as an empty space. */ class LEARNUE4CPP_API SCumstomButton : public SButton { public: UTexture2D* AdvancedHitTexture; int AdvancedHitAlpha; SCumstomButton() : AdvancedHitTexture(NULL), AdvancedHitAlpha(0) {} void SetAdvancedHitTexture(UTexture2D* InTexture) { AdvancedHitTexture = InTexture; } void SetAdvancedHitAlpha(int InAlpha) { AdvancedHitAlpha = InAlpha; } virtual FReply OnMouseButtonDown(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) override { if (!bIsHovered) return FReply::Unhandled(); return SButton::OnMouseButtonDown(MyGeometry, MouseEvent); } virtual FReply OnMouseButtonDoubleClick(const FGeometry& InMyGeometry, const FPointerEvent& InMouseEvent) override { if (!bIsHovered) return FReply::Unhandled(); return SButton::OnMouseButtonDoubleClick(InMyGeometry, InMouseEvent); } virtual FReply OnMouseButtonUp(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) override { if (!bIsHovered) return FReply::Unhandled(); return SButton::OnMouseButtonUp(MyGeometry, MouseEvent); } virtual FReply OnMouseMove(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) override; virtual void OnMouseEnter(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) override { if (AdvancedHitTexture) return; return SButton::OnMouseEnter(MyGeometry, MouseEvent); } virtual void OnMouseLeave(const FPointerEvent& MouseEvent) override { return SButton::OnMouseLeave(MouseEvent); } virtual FCursorReply OnCursorQuery(const FGeometry& MyGeometry, const FPointerEvent& CursorEvent) const override; virtual TSharedPtr<IToolTip> GetToolTip() override { return (bIsHovered ? SWidget::GetToolTip() : NULL); } }; /** * */ UCLASS() class LEARNUE4CPP_API UCustomButton : public UButton { GENERATED_BODY() public: UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "AdvancedHitTest") UTexture2D* AdvancedHitTexture; UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "AdvancedHitTest", meta = (ClampMin = "0.0", ClampMax = "255.0", UIMin = "0.0", UIMax = "255.0")) int AdvancedHitAlpha; UFUNCTION(BlueprintCallable, Category = "AdvancedHitTest") void SetAdvancedHitTexture(UTexture2D* InTexture) { AdvancedHitTexture = InTexture; if (MyButton.IsValid()) (static_cast<SCumstomButton*>(MyButton.Get()))->SetAdvancedHitTexture(AdvancedHitTexture); } UFUNCTION(BlueprintCallable, Category = "AdvancedHitTest") void SetAdvancedHitAlpha(int InAlpha) { AdvancedHitAlpha = InAlpha; if (MyButton.IsValid()) (static_cast<SCumstomButton*>(MyButton.Get()))->SetAdvancedHitAlpha(AdvancedHitAlpha); } UCustomButton(const FObjectInitializer& ObjectInitializer) : AdvancedHitTexture(NULL), AdvancedHitAlpha(NULL), Super(ObjectInitializer) {} virtual void SynchronizeProperties() override; virtual TSharedRef<SWidget> RebuildWidget() override; };
// CustomButton.cpp // Fill out your copyright notice in the Description page of Project Settings. #include "LearnUE4Cpp.h" #include "CustomButton.h"
#pragma region >>> SCustomButton <<<
FReply SCumstomButton::OnMouseMove(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent)
{
if (!AdvancedHitTexture) return SButton::OnMouseMove(MyGeometry, MouseEvent);
bool WhatToReturn = true;
FVector2D LocalPosition = MyGeometry.AbsoluteToLocal(MouseEvent.GetScreenSpacePosition());
LocalPosition.X = floor(LocalPosition.X);
LocalPosition.Y = floor(LocalPosition.Y);
LocalPosition /= MyGeometry.GetLocalSize();
int ImageWidth = AdvancedHitTexture->PlatformData->SizeX;
LocalPosition.X *= ImageWidth;
LocalPosition.Y *= AdvancedHitTexture->PlatformData->SizeY;
int BufferPosition = (LocalPosition.Y * ImageWidth) + LocalPosition.X;
FColor* ImageData = static_cast<FColor*>((AdvancedHitTexture->PlatformData->Mips[0]).BulkData.Lock(LOCK_READ_ONLY));
if (!ImageData)
{
WhatToReturn = false;
}
else
{
if (ImageData[BufferPosition].A <= AdvancedHitAlpha) WhatToReturn = false;
}
AdvancedHitTexture->PlatformData->Mips[0].BulkData.Unlock();
if (WhatToReturn != bIsHovered)
{
bIsHovered = WhatToReturn;
if (bIsHovered) SButton::OnMouseEnter(MyGeometry, MouseEvent);
else SButton::OnMouseLeave(MouseEvent);
}
return SButton::OnMouseMove(MyGeometry, MouseEvent);
}
FCursorReply SCumstomButton::OnCursorQuery(const FGeometry& MyGeometry, const FPointerEvent& CursorEvent) const {
if (!bIsHovered) return FCursorReply::Unhandled();
TOptional<EMouseCursor::Type> TheCursor = Cursor.Get();
return (TheCursor.IsSet()) ? FCursorReply::Cursor(TheCursor.GetValue()) : FCursorReply::Unhandled();
}
#pragma endregion
#pragma region >>> UCustomButton <<<
void UCustomButton::SynchronizeProperties()
{
Super::SynchronizeProperties();
(static_cast<SCumstomButton*>(MyButton.Get()))->SetAdvancedHitTexture(AdvancedHitTexture);
(static_cast<SCumstomButton*>(MyButton.Get()))->SetAdvancedHitAlpha(AdvancedHitAlpha);
}
TSharedRef<SWidget> UCustomButton::RebuildWidget()
{
TSharedPtr<SCumstomButton> CustomButton = SNew(SCumstomButton)
.OnClicked(BIND_UOBJECT_DELEGATE(FOnClicked, SlateHandleClicked))
.OnPressed(BIND_UOBJECT_DELEGATE(FSimpleDelegate, SlateHandlePressed))
.OnReleased(BIND_UOBJECT_DELEGATE(FSimpleDelegate, SlateHandleReleased))
.OnHovered_UObject(this, &ThisClass::SlateHandleHovered)
.OnUnhovered_UObject(this, &ThisClass::SlateHandleUnhovered)
.ButtonStyle(&WidgetStyle)
.ClickMethod(ClickMethod)
.TouchMethod(TouchMethod)
.IsFocusable(IsFocusable)
;
CustomButton->SetAdvancedHitTexture(AdvancedHitTexture);
CustomButton->SetAdvancedHitAlpha(AdvancedHitAlpha);
MyButton = CustomButton;
if (GetChildrenCount() > 0) Cast<UButtonSlot>(GetContentSlot())->BuildSlot(MyButton.ToSharedRef());
return MyButton.ToSharedRef();
}
#pragma endregion
把上面的代码复制到你的项目中, 根据自己的实际项目名称和类名称进行修改。编译成功后打开UE4创建UMG, 这时就会在UMG的Palette面板 Common分类中看到通过C++定义的按钮。把按钮拖拽到Canvas上,在Details面板中的AdvancedHitTest分类下边的Advanced Hit Texture 设置为你按钮想显示的图片。图片的主显示内容以外的区域必须是全透明的,否则无效。 Appearenace->Style:
Normal, Hovered, Pressed 都设置为相同的图片,并且DrawAs属性设置为Image
运行,最终效果如下,鼠标只有在图形上边点击才会响应点击事件
相关文章推荐
- Swing 实现简单的自定义不规则按钮组件
- Swing 实现简单的自定义不规则按钮组件2
- 自定义形状按钮的实现
- Android 实现不规则形状按钮
- 使用GDI加载PNG实现自定义不规则按钮
- 实现不规则形状的按钮
- win32 api 实现不规则形状按钮
- 不规则对话框的实现 C++
- SQL如何实现自定义排序规则
- [C++再学习系列] 派生类函数的重实现规则(override-覆盖)
- GridView中自定义单选按钮列的实现!
- 在SQL和ERWIN中用自定义类型、规则和默认值实现check约束从而保证数据的完整性
- C++ GUI Programming with Qt 4 - 10.3 实现自定义模型
- C++ GUI Programming with Qt 4 - 10.3 实现自定义模型
- 在C++中用虚函数及模版实现委托(支持自定义参数)(转)
- C++实现自绘按钮控制
- QtWidget: 自定义不规则窗体与按钮
- .net实现自定义UBB代码及规则的基本实现
- 主界面设计+自定义按钮实现tab控件功能
- 使用profile的PASSWORD_VERIFY_FUNCTION参数实现自定义的密码验证规则