activex 如何调用OnDraw函数

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了activex 如何调用OnDraw函数相关的知识,希望对你有一定的参考价值。

在最初显示或重新绘制 ActiveX 控件时,控件遵循与使用 MFC 开发的其他应用程序相似的过程,但有一个重要的区别:ActiveX 控件可以是活动状态或非活动状态。

活动控件在 ActiveX 控件容器中由子窗口表示。与其他窗口一样,活动控件负责在接收到 WM_PAINT 消息时绘制自身。控件的基类 COleControl 在其 OnPaint 函数中处理此消息。此默认实现调用控件的 OnDraw 函数。

非活动控件的绘制过程与此不同。当控件处于非活动状态时,其窗口不可见或不存在,因此无法接收绘制消息。相反,控件容器直接调用控件的 OnDraw 函数。此过程与活动控件的绘制过程不同,因为从不调用 OnPaint 成员函数。

如以上段落所讨论的,如何更新 ActiveX 控件取决于控件的状态。但是,由于框架在两种情况中都调用 OnDraw 成员函数,因此在此成员函数中添加大部分绘制代码。

OnDraw 成员函数处理控件的绘制。当控件处于非活动状态时,控件容器调用 OnDraw,并传递控件容器的设备上下文和该控件所占据的矩形区域的坐标。

框架传递给 OnDraw 成员函数的矩形包含控件占据的区域。如果控件处于活动状态,则左上角是 (0, 0),并且传递的设备上下文是包含该控件的子窗口的设备上下文。如果控件处于非活动状态,则左上角的坐标不一定是 (0, 0),并且传递的设备上下文是包含该控件的控件容器的设备上下文。

其余请见参考资料部分。
下面是咱自己的心得:就像大多数GUI一样,当图形需要初始化时,OnDraw函数响应ONPAINT消息,工程起初生成的三大基类之中的COleControl调用OnPaint方法,OnPaint方法调用OnDraw函数执行绘制;如果控件已被初始化且重新回到活动状态时(重绘),就直接调OnDraw方法。

参考资料:http://msdn.microsoft.com/zh-cn/library/cc451433(v=vs.71).aspx

参考技术A 写好OnDraw();
在OnInititalUpdate()里面调用就好啦

onDraw 函数被调用两次?

【中文标题】onDraw 函数被调用两次?【英文标题】:onDraw function gets called twice? 【发布时间】:2020-01-04 01:28:02 【问题描述】:

我很难找到这里的错误。我有一个 AlertDialog.Builder 启动了一个自定义对话框,我应该在其中使用 arcDraw 和 Canvas 绘制一个 PieChart,问题是如果我使用调试器使用该应用程序,我可以看到我的图表第一次绘制正确,然后第二次调用进入并且把一切都搞砸了,我不知道它是从哪里来的,需要帮助,一些想法吗?

代码:

package com.example.proiect_stroescumarius.ui;

import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.RatingBar;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.fragment.app.Fragment;

import com.example.proiect_stroescumarius.OnDataPassListener;
import com.example.proiect_stroescumarius.R;
import com.example.proiect_stroescumarius.data.RoomDbInstance;
import com.example.proiect_stroescumarius.data.SharedPrefs;
import com.example.proiect_stroescumarius.data.User;

import java.util.ArrayList;
import java.util.List;

public class ListUsersFragment extends Fragment 

    private RatingBar ratingBar;
    private TextView tv;
    private TextView ipPrimit;
    private ListView listView;
    private RoomDbInstance roomDbInstance;
    private OnDataPassListener listener;
    private UserListAdapter userListAdapter;
    private Button pieChartBtn;
    private ListUsersFragment fragment = this;
    private int nrRecords = 0;
    private List<User> users;
    private ArrayList<User> arrayList = new ArrayList<>();
    boolean ponderiCalculate = false;


    public View onCreateView(@NonNull LayoutInflater inflater,
                             ViewGroup container, Bundle savedInstanceState) 

        View root = inflater.inflate(R.layout.fragment_listsearch, container, false);
        roomDbInstance = RoomDbInstance.getInstance(getContext());
        listView = root.findViewById(R.id.list_users);
        userListAdapter = new UserListAdapter(root.getContext(), R.layout.customadapter, arrayList);
        SharedPrefs sharedPrefs = new SharedPrefs(root.getContext());
        ratingBar = root.findViewById(R.id.ratingBar);
        tv = root.findViewById(R.id.ratingTV);
        ConstraintLayout layout = root.findViewById(R.id.layoutList);
        listener.convertFont(sharedPrefs.getFont(), this, layout);

        pieChartBtn = root.findViewById(R.id.pieChartBtn);
        populateAdapter();
        displayRating();
        updateListView();
        pieChartBtn.setOnClickListener(new View.OnClickListener() 
            @Override
            public void onClick(View v) 
                AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
                builder.setMessage("No entries so can't create any charts...");
                builder.setCancelable(true).setPositiveButton("OK", new DialogInterface.OnClickListener() 
                    @Override
                    public void onClick(DialogInterface dialog, int which) 
                        AlertDialog builder2 = builder.create();
                        builder2.dismiss();
                    
                ).create();
                if (nrRecords == 0) builder.show();
                else 
                    AlertDialog.Builder builder1 = new AlertDialog.Builder(getActivity());
//                    LayoutInflater inflater = getLayoutInflater();
                    View v1 = inflater.inflate(R.layout.pie_chart,null);
                    RelativeLayout layout = v1.findViewById(R.id.layoutPieChart);

                    PieInfo pieInfo = calculPonderi();
                    builder1.setView(v1).show();

                    float[] deCalculat = new float[pieInfo.pondereCountries.size()];
                    Toast.makeText(getContext(), String.valueOf(deCalculat[0]), Toast.LENGTH_SHORT).show();
                    int index = 0;
                    for (Float f : pieInfo.pondereCountries) 
                        deCalculat[index++] = f;
                    
//        Log.d("pie",String.valueOf(deCalculat.length));
//        layout.setLayoutParams(new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT));

                    float[] temp = new float[]1, 2;

                    PieChartView pieChart = new PieChartView(getContext(), calculateValues(deCalculat));

                    RelativeLayout.LayoutParams pieLayout = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
                    pieLayout.setMargins(200, 10, 0, 0);
                    pieChart.setLayoutParams(pieLayout);
                    layout.addView(pieChart);

                    int x = 850;
                    int y = 860;
                    for (String country : pieInfo.listCountries) 
                        RelativeLayout.LayoutParams tvLayout = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT,
                                RelativeLayout.LayoutParams.WRAP_CONTENT);
                        tvLayout.setMargins(70, x, 0, 0);
                        x += 80;
                        TextView legend = new TextView(getContext());
                        legend.setText(country);
                        legend.setLayoutParams(tvLayout);
                        layout.addView(legend);
                        int[] colorsChart = pieChart.colors;
                        int nrCuloare = pieInfo.listCountries.indexOf(country);


                        RelativeLayout.LayoutParams imgViewLayout = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT,
                                RelativeLayout.LayoutParams.WRAP_CONTENT);
                        imgViewLayout.height = 50;
                        imgViewLayout.width = 50;
                        imgViewLayout.setMargins(10, y, 0, 0);
                        ImageView imageView = new ImageView(getContext());
                        imageView.setBackgroundColor(colorsChart[nrCuloare]);
                        imageView.setLayoutParams(imgViewLayout);
                        layout.addView(imageView);

                        y += 80;
                    
                

            
        );

        return root;
    

    private float[] calculateValues(float[] values) 
        Log.d("onDraw_CalculateValues","being_CALLED");
        float total = 0;
        float[] degreeValues = new float[values.length];
        for (int i = 0; i < values.length; i++) 
            total += values[i];
        
        for (int i = 0; i < values.length; i++) 
            degreeValues[i] = 360 * (values[i] / total);
        
        return degreeValues;
    

    private void updateListView() 

        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() 
            @SuppressLint("StaticFieldLeak")
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) 
                Object u = listView.getItemAtPosition(position);
                User user = (User) u;
                createDialog(user);
            
        );

        listView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() 
            @SuppressLint("StaticFieldLeak")
            @Override
            public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) 
                Object deleteUser = listView.getItemAtPosition(position);
                new AsyncTask<Void, Void, Void>() 
                    @Override
                    protected Void doInBackground(Void... voids) 
                        roomDbInstance.getUsersDao().eraseUser((User) deleteUser);
                        return null;
                    

                    @Override
                    protected void onPostExecute(Void aVoid) 
                        super.onPostExecute(aVoid);
                        userListAdapter.remove((User) deleteUser);
                        nrRecords = userListAdapter.getCount();
                        userListAdapter.notifyDataSetChanged();
                    
                .execute();
                return false;
            
        );
    

    private void createDialog(User received) 
        AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
        LayoutInflater inflater = getLayoutInflater();
        View view = inflater.inflate(R.layout.update_user, null);
        TextView ip_Update = view.findViewById(R.id.ip_updateUser);
        TextView nickname = view.findViewById(R.id.nickname_updateUser);
        ip_Update.setText(received.getIp());
        nickname.setText(received.getNickname());
        Button updateBtn = view.findViewById(R.id.btn_update);
        builder.setView(view);
        AlertDialog dialog1 = builder.show();

        updateBtn.setOnClickListener(new View.OnClickListener() 
            @Override
            public void onClick(View v) 
                if (!nickname.getText().toString().equals(received.getNickname())) 
                    InputMethodManager inputMethodManager = (InputMethodManager)
                            getActivity().getApplicationContext().getSystemService(getContext().INPUT_METHOD_SERVICE);
                    // Hide the soft keyboard
                    inputMethodManager.hideSoftInputFromWindow(nickname.getWindowToken(), 0);
                    received.setNickname(nickname.getText().toString());
                    userListAdapter.notifyDataSetChanged();
                    updateOnDatabase(received.getId(), nickname.getText().toString());
                    dialog1.dismiss();
                 else 
                    AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
                    builder.setMessage("No changes?");
                    builder.setCancelable(true);
                    builder.setPositiveButton("Yup", new DialogInterface.OnClickListener() 
                        @Override
                        public void onClick(DialogInterface dialog, int which) 

                        
                    );
                    builder.setNegativeButton("Nope", new DialogInterface.OnClickListener() 
                        @Override
                        public void onClick(DialogInterface dialog, int which) 
                            dialog1.dismiss();
                        
                    );
                    builder.show();
                
            

            @SuppressLint("StaticFieldLeak")
            private void updateOnDatabase(int id, String new_nickname) 
                new AsyncTask<Void, Void, Void>() 
                    @Override
                    protected Void doInBackground(Void... voids) 
                        roomDbInstance.getUsersDao().updateUser(id, new_nickname);
                        return null;
                    
                .execute();
            
        );

        nickname.setOnEditorActionListener(new TextView.OnEditorActionListener() 
            @Override
            public boolean onEditorAction(TextView v, int actionId, KeyEvent event) 
                if (actionId == EditorInfo.IME_ACTION_DONE) 
                    InputMethodManager inputMethodManager = (InputMethodManager)
                            getActivity().getApplicationContext().getSystemService(getContext().INPUT_METHOD_SERVICE);
                    // Hide the soft keyboard
                    inputMethodManager.hideSoftInputFromWindow(nickname.getWindowToken(), 0);
//                    Toast.makeText(getContext(), nickname.getText(), Toast.LENGTH_SHORT).show();
                    return true;
                
                return false;
            
        );

    

    public class PieInfo 
        ArrayList<String> listCountries = new ArrayList<>();
        ArrayList<Float> pondereCountries = new ArrayList<>();

        PieInfo() 

        

        public ArrayList<String> getListCountries() 
            return listCountries;
        

        public void setListCountries(ArrayList<String> listCountries) 
            this.listCountries = listCountries;
        

        public ArrayList<Float> getPondereCountries() 
            return pondereCountries;
        

        public void setPondereCountries(ArrayList<Float> pondereCountries) 
            this.pondereCountries = pondereCountries;
        
    

    private PieInfo calculPonderi() 
        PieInfo pieInfo = new PieInfo();
//         ArrayList<String> listCountries = new ArrayList<>();
//         ArrayList<Float> pondereCountries = new ArrayList<>();
        for (int j = 0; j < users.size(); j++) 
            float counterCountry = 1;
            String aux = users.get(j).getCountry();
            pieInfo.listCountries.add(aux);
            for (int i = 0; i < arrayList.size(); i++) 
                if (aux.equals(arrayList.get(i).getCountry())) 
                    counterCountry++;
                
            
//            Toast.makeText(getContext(),String.valueOf(counterCountry), Toast.LENGTH_SHORT).show();
            pieInfo.pondereCountries.add(counterCountry);
        
        return pieInfo;
    

    @SuppressLint("StaticFieldLeak")
    private void populateAdapter() 
//        Log.d("populateReached","Reached!");

        new AsyncTask<Void, Void, Void>() 
            @Override
            protected Void doInBackground(Void... voids) 
                users = roomDbInstance.getUsersDao().getAllUsers();
                arrayList.addAll(users);
                return null;
            

            @Override
            protected void onPostExecute(Void aVoid) 
                super.onPostExecute(aVoid);
                listView.setAdapter(userListAdapter);
                nrRecords = userListAdapter.getCount();
                userListAdapter.notifyDataSetChanged();
            

        .execute();

    

    public ListUsersFragment() 
        //Required empty constructor
    

    private void displayRating() 
        ratingBar.setOnRatingBarChangeListener(new RatingBar.OnRatingBarChangeListener() 
            @Override
            public void onRatingChanged(RatingBar ratingBar, float rating, boolean fromUser) 
                Toast.makeText(getContext(), "" + rating, Toast.LENGTH_SHORT).show();
                tv.setText("Thanks for the feedback!");

            
        );
    

    @Override
    public void onAttach(Context context) 
        super.onAttach(context);
        listener = (OnDataPassListener) getActivity();
    

    public class PieChartView extends View 

        private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        private int[] colors = Color.BLACK, Color.CYAN, Color.GREEN, Color.RED, Color.BLUE;
        private RectF rectangle = new RectF(10, 10, 800, 800);
        private float[] valueDegrees;
        private float tmp = 0;

        public PieChartView(Context context, float[] values) 
            super(context);
            valueDegrees = new float[values.length];
            for (int i = 0; i < valueDegrees.length; i++) 
                valueDegrees[i] = values[i];
            
        

        @Override
        protected void onDraw(Canvas canvas) 
            super.onDraw(canvas);
            for (int i = 0; i < valueDegrees.length; i++) 
                if (i == 0) 
                    paint.setColor(colors[i]);
                    canvas.drawArc(rectangle, 0, valueDegrees[i], true, paint);
                 else 
                    tmp += valueDegrees[i - 1];
                    paint.setColor(colors[i]);
                    canvas.drawArc(rectangle, tmp, valueDegrees[i], true, paint);
                
            
            Log.d("onDraw","beingCalled");
        
    

【问题讨论】:

第二次它显示的颜色比它应该显示的颜色少,但空间划分保持正确,尝试不使用 AlertDialog,它就像一个魅力,但我需要在同一片段中的单独窗口中显示 PieChart .. 【参考方案1】:

您必须了解,对于给定的ViewonDraw() 通常会被多次调用。它是 Android 屏幕刷新机制的一部分。在这种情况下,这可能是因为View 大小的微小变化(由于重新布局)。

因此,最好限制 onDraw() 函数更改对象的状态。您的PieChartView 违反了该原则; tmp 正在更改中。

要解决此问题,请将 tmp 设为局部变量,而不是成员变量。

【讨论】:

感谢您的见解和宝贵的时间。

以上是关于activex 如何调用OnDraw函数的主要内容,如果未能解决你的问题,请参考以下文章

【急】js中调用ActiveX控件中的函数?

Invalidate 未调用自定义视图类的 onDraw

MFC中啥时候调用OnDraw()函数?

在 MFC SDI 应用程序中调用 OnDraw

C#调用ActiveX ClsID, COM ProgID, Runtime Type动态创建对象

ondraw 函数没有在 mfc 中调用?